Redis事務可讓一個客戶端在不被其餘客戶端打斷的狀況下執行多個命令,和關係數據庫那種能夠在執行的過程當中進行回滾(rollback)的事務不一樣,在Redis裏面,被MULTI
命令和EXEC
命令包圍的全部命令會一個接一個地執行,直到全部命令都執行完畢爲止。當一個事務執行完畢以後,Redis纔會處理其餘客戶端的命令。node
當Redis從一個客戶端那裏接收到MULTI
命令時,Redis會將這個客戶端以後發送的全部命令都放入到一個隊列裏面,直到這個客戶端發送EXEC
命令爲止,Redis纔會在不被打斷的狀況下,一個接一個地執行存儲在隊列裏面的命令。redis
有時候還會用到UNWATCH
或DISCARD
命令。在用戶使用WATCH
命令對鍵進行監視以後,直到用戶執行EXEC
命令的這段時間裏面,若是有其餘客戶端搶先對任何被監視的鍵進行了更新或刪除等操做,那麼用戶嘗試執行EXEC
命令時,事務將失敗並返回一個錯誤(以後用戶能夠選擇重試事務或者放棄事務)。經過使用WATCH
、MULTI
/EXEC
、 UNWATCH
/DISCARD
等命令,程序能夠在執行某些重要操做的時候,經過確保本身正在使用的數據沒有發生變化避免數據出錯。 數據庫
由於加鎖有可能會形成長時間的等待,因此Redis爲了儘量地減小客戶端的等待時間,並不會在執行WATCH命令時對數據進行加鎖。Redis只會在數據被其餘客戶端搶先修改的狀況下,通知執行了WATCH命令的客戶端,這種作法被稱爲樂觀鎖(optimistic locking),而關係數據庫實際執行的加鎖操做則被稱爲悲觀鎖(pessimistic locking)。樂觀鎖在實際使用中一樣很是有效,由於客戶端永遠沒必要花時間去等待第一個取得鎖的客戶端——它們只須要在本身的事務執行失敗時進行重試就能夠了。安全
UNWATCH命令能夠在WATCH命令執行以後、MULTI命令執行以前對鏈接進行重置(reset);一樣地,DISCARD命令也能夠在MULTI命令執行以後、EXEC命令執行以前對鏈接進行重置。這也就是說,用戶在使用WATCH監視一個或多個鍵,接着使用MULTI開始一個新的事務,並將多個命令入隊到事務隊列以後,仍然能夠經過發送DISCARD命令來取消WATCH命令並清空全部已入隊命令。服務器
StackExchange.Redis 事務示例代碼網絡
using (var redis = ConnectionMultiplexer.Connect(redisConnectionStr))
{
var db = redis.GetDatabase(); var tran = db.CreateTransaction();//MULTI tran.AddCondition(Condition.HashNotExists("key", "UniqueID")); //WATCH //tran.AddCondition(Condition.StringEqual("name", name)); bool committed = tran.Execute(); //EXEC }
Redis實戰一書中有提到非事物流水總線,即命令並不須要放在事務裏面執行,經過一次發送全部命令來減小通訊次數並下降延遲值。StackExchange.Redis將這部分封裝爲Batch。app
Batch會把所須要執行的命令打包成一條請求發到Redis,而後一塊兒等待返回結果。less
using (var redis = ConnectionMultiplexer.Connect(redisConnectionStr))
{
var db = redis.GetDatabase(); var batch = db.CreateBatch(); Task t1 = batch.StringSetAsync("name", "bob"); Task t2 = batch.StringSetAsync("age", 100); batch.Execute(); Task.WaitAll(t1, t2); }
流水線(Pipelining)可讓咱們同時發送多個請求,從而減輕延遲。socket
using (var redis = ConnectionMultiplexer.Connect(redisConnectionStr))
{
var db = redis.GetDatabase(); var aPending = db.StringSetAsync("a","a"); var bPending = db.StringSetAsync("b","b"); var a = db.Wait(aPending); var b = db.Wait(bPending); //一樣能夠用aPending.Wait() 或 Task.WaitAll(aPending, bPending)代替 }
關於Batch和Pipelining的區別:Batch模式不會與同一個Multiplexing內的競爭從而交叉操做(我的理解)。tcp
參考鏈接:https://stackoverflow.com/questions/27796054/pipelining-vs-batching-in-stackexchange-redis
Redis提供了兩種不一樣的持久化方法。一種方法叫快照(snapshotting),它能夠將某一時刻的全部數據都寫入硬盤裏面。另外一種方法叫只追加文件(append-only file,AOF),它會在執行寫命令時,將被執行的寫命令複製到硬盤裏面。這兩種持久化方法既可單獨使用又能夠同時使用。
Redis能夠經過建立快照來得到存儲在內存裏面的數據在某個時間點上的副本。
redis.conf配置文件中
################################ SNAPSHOTTING ################################
部分有作說明
save 900 1 表示900秒內至少發生過一次更改就會自動觸發BGSAVE命令
若是設置了多個save
配置選項,那麼當任意一個save
所設置的條件被知足時,Redis就會觸發一次BGSAVE
命令。
save "" 會刪除以前配置的全部保存條件
快照發生錯誤是否中止寫數據。
By default Redis will stop accepting writes if RDB snapshots are enabled (at least one save point) and the latest background save failed.
是否對快照文件進行壓縮
是否對快照文件進行校驗
指定存儲的文件名
指定存儲路徑
AOF持久化將被執行的寫命令寫到AOF文件的末尾,以此來記錄數據發生的變化。Redis只要從頭至尾從新執行一次AOF文件包含的全部寫命令,就能夠恢復AOF文件所記錄的數據。
AOF持久化很是靈活地提供了多種不一樣的選項來知足不一樣應用程序對數據安全的不一樣要求,但AOF持久化也有缺陷——那就是AOF文件的體積過大。Redis會不斷地將執行的命令記錄到AOF文件裏面,因此隨着Redis運行,AOF文件的體積也會不斷增加。
AOF工做流程
全部的寫入命令會追加到aof_buf(緩衝區)中。
AOF緩衝區根據對應的策略向硬盤作同步操做。
隨着AOF文件愈來愈大,須要按期對AOF文件進行重寫,達到壓縮的目的。
當Redis服務器重啓時,能夠加載AOF文件進行數據恢復。
redis.conf配置文件中
############################## APPEND ONLY MODE ###############################
部分有作說明
是否開啓AOF持久化
設置AOF文件名,默認文件名是appendonly.aof
設置同步頻率
If unsure, use "everysec".
主進程在寫AOF文件採用always或者everysec配置,和子進程在重寫AOF文件的時候,都會產生大量的I/O操做。可能會使fsync阻塞很長時間,
若是開啓該參數,表示在bgsave和bgrewriteaof的過程當中,主線程寫入AOF不會調用fsync(),至關於配置appendfsync no。這樣有可能會致使redis的修改命令丟失,Linux默認配置下,最多丟失30秒的數據。
若是關閉該參數,表示在bgsave和bgrewriteaof的過程當中,主線程寫入AOF會調用fsync(),而且被阻塞,這樣是最安全的,不會丟失數據。
AOF文件的體積比上一次重寫以後的體積大了至少一倍(100%)的時執行BGREWRITEAOF
命令重寫
BGREWRITEAOF
的工做原理和BGSAVE
建立快照的工做原理很是類似:Redis會建立一個子進程,而後由子進程負責對AOF文件進行重寫。指定零百分比能夠禁用自動AOF重寫功能。
當AOF文件的體積大於64MB時執行BGREWRITEAOF
命令重寫
若是該配置啓用,在加載時發現AOF尾部不正確,會向客戶端寫入一個log,可是會繼續執行,若是設置爲 no
,發現錯誤就會中止,必須修復後才能從新加載。
RDB AOF 混合開啓。Redis5.0新增功能,AOF重寫及恢復可使用RDB文件及AOF文件,速度更快,默認yes
不管是快照持久化仍是AOF持久化,都提供了在遇到系統故障時進行數據恢復的工具。Redis提供了兩個命令行程序redis-check-aof和redis-check-rdb (redis-check-dump in 3.0 and below),它們能夠在系統故障發生以後,檢查AOF文件和快照文件的狀態,並在有須要的狀況下對文件進行修復。
程序修復AOF文件的方法很是簡單:它會掃描指定的AOF文件,當發現第一個出錯命令的時候,程序會刪除出錯的命令以及位於出錯命令以後的全部命令。在大多數狀況下,被刪除的都是AOF文件末尾的不完整的寫命令。
擴展平臺以適應更高負載,複製(replication)是不可或缺的。Redis須要擴展讀請求或者在須要寫入臨時數據的時,用戶能夠經過設置額外的Redis從服務器來保存數據的副本。接收到主服務器發送的數據初始副本(initial copy of the data)以後,客戶端每次向主服務器寫入數據時,從服務器都會實時獲得更新。部署好主從服務器以後,客戶端就能夠向任意一個從服務器發送讀請求,而沒必要把每一個讀請求都發送給主服務器。
將服務器設置爲從服務器
從 5.0.0 版本開始,Redis 正式將 SLAVEOF 命令更名成了 REPLICAOF 命令並逐漸廢棄原來的 SLAVEOF 命令
對於一個正在運行的Redis服務器,用戶能夠經過發送REPLICAOF no one命令來讓服務器終止複製操做,再也不接受主服務器的數據更新,服務器在中止複製以後不會清空數據庫,而是會繼續保留複製產生的全部數據;也能夠經過發送REPLICAOF
host port
命令來讓服務器開始複製一個新的主服務器。
指定主服務器的鏈接密碼
當從庫同主機失去鏈接或者複製正在進行,從機庫有兩種運行方式:
1) 若是slave-serve-stale-data設置爲yes(默認設置),從庫會繼續響應客戶端的請求。
2) 若是slave-serve-stale-data設置爲no, INFO,replicaOF, AUTH, PING, SHUTDOWN, REPLCONF, ROLE, CONFIG,SUBSCRIBE, UNSUBSCRIBE, PSUBSCRIBE, PUNSUBSCRIBE, PUBLISH, PUBSUB,COMMAND, POST, HOST: and LATENCY命令以外的任何請求 都會返回一個錯誤」SYNC with master in progress」。
做爲從服務器,默認狀況下是隻讀的(yes),能夠修改爲NO,用於寫(不建議)
是否使用socket方式複製數據。目前redis複製提供兩種方式,disk和socket。
2種方式區別:disk方式是master建立一個新的進程把rdb文件保存到磁盤,再把磁盤上的rdb文件傳遞給slave。socket是master建立一個新的進程,直接把rdb文件以socket的方式發給slave。disk方式的時候,當一個rdb保存的過程當中,多個slave都能共享這個rdb文件。socket的方式就的一個個slave順序複製。在磁盤速度緩慢,網速快的狀況下推薦用socket方式。
啓用無磁盤複製時,能夠配置延遲時間。若是設置爲0,表明一旦複製開始,節點不會再接收新slave的複製請求直到下一個rdb傳輸。因此最好設置一個等待時間,等更多的slave連上來
根據指定的時間間隔向服務器發送ping請求
複製鏈接超時時間。主從服務器都有超時時間的設置。須要注意的是repl-timeout須要設置爲一個比repl-ping-slave-period更大的值,不然會常常檢測到超時
是否禁用TCP_NODELAY。
若是你選擇‘yes’,Redis將使用較少數量的TCP數據包和不多的帶寬向副本發送數據。 可是這可能會增長數據在副本上出現的延遲,使用默認配置的Linux內核,最多可延遲40毫秒。
若是選擇‘no’,則數據出如今副本上的延遲將會減小,但這將使用更多的帶寬來進行復制。
在很是高流量的條件下推薦使用yes。
複製緩衝區大小,緩衝區的大小越大,slave離線的時間能夠更長,複製緩衝區只有在有slave鏈接的時候才分配內存。沒有slave的一段時間,內存會被釋放出來,默認1m
設置複製緩衝區的內存釋放的時間,單位爲秒。
當master不可用,會根據slave的優先級選舉一個master。最低優先級的slave,當選master。配置成0,永遠不會被選舉
表示鏈接到master的最少slave數量
延遲小於min-replicas-max-lag秒的slave才認爲是健康的slave
向其主服務器報告特定的IP
向其主服務器報告特定的端口
建立多個從服務器可能會形成網絡不可用——當複製須要經過互聯網進行或者在不一樣數據中心之間進行時,尤其如此。Redis的主服務器和從服務器並無特別不一樣的地方,因此從服務器也能夠擁有本身的從服務器,並由此造成主從鏈(master/slave chaining)。