Redis持久化
RDB方式
RDB方式持久化是通過快照(snapshotting)完成的,當符合一定條件時自動將內存中的所有數據生成一份副本並存在硬盤上。
根據配置規則進行自動快照
由兩個參數:時間窗口M和改動的鍵的個數N,每當時間M內被更改的鍵的個數大於N時,即符合自動快照條件,每條快照條件佔一行並且以save參數開頭,例:
15分鐘內(900秒)有一個或一個以上的鍵被更改進行快照
save 900 1
save 300 10
save 60 1000
*當執行SAVE命令時,Redis同步地進行快照操作,在快照執行的過程中會阻塞所有來自客戶端的請求。當數據比較多時,這一過程會導致Redis較長時間不能響應
*BGSAVE命令可以在後臺異步地進行快照操作,快照的同時服務器還能繼續響應客戶端的請求。
*LASTSAVE命令獲取最近一次成功快照的時間,返回Unix時間戳
*FLUSHALL會清除數據庫中的所有數據,不論清空數據庫的過程是否觸發了自動快照條件,只要自動快照條件不爲空,Redis就會執行一次快照操作。如果沒有定義自動快照條件,執行FLUSHALL則不會進行快照
*執行復制(replication)時,當設置了主從模式時,Redis會在複製初使化時進行快照。
*Radis默認會將快照文件存儲在Redis當前進程的工作目錄中的dump.rdb文件中,可以通過配置dir和dbfilename兩個參數分別指定快照文件存儲的路徑和文件名。
快照過程如下:
1.Redis使用fork函數複製一份當前進程(父進程)的副本(子進程)
2.父進程繼續接收並處理客戶端發來的命令,而子進程開始將內存中的數據寫入硬盤中的臨時文件
3.當子進程寫入完所有數據後會用該臨時文件替換舊的RDB文件
在執行fork的時候操作系統會使用寫時複製(copy-on-write)策略,即fork函數發生的一刻父子進程共享同一內存數據,當父進程要更改其中某片數據時,系統會將該片數據複製一份以保證子進程的數據不受影響,所以新的RDB文件存儲的是執行fork一刻的內存數據。
寫時複製微略也保證了fork時刻雖然看上去生成兩份內存副本,但實際內存的佔用量不會增加一倍。
/etc/sysctl.conf文件中加入vm.overcommit_memory =1 linux系統設置應用可以申請超過可用內存(物理內存和交換分區)的空間,重啓系統或執行sysctl vm.overcommit_memory=1 使生效。
當快照過程中,如果寫入操作過多,造成fork前後數據差異較大,會使內存使用量顯著超過實際數據大小。
RDB文件是經過壓縮的二進制格式,rdbcompression參數可以設置禁用壓縮節省cpu。
Redis啓動後會讀取RDB快照文件,將數據從硬盤載入到內存,通常一個記錄1000萬個字符串類型鍵,大小爲1G的快照文件載入到內存需要20-30秒。
AOF方式
當使用Redis存儲非臨時數據時,一般需要打開AOF持久化來降低進程中止導致的數據丟失,AOF將Redis執行的每一條寫命令追加到硬盤文件中。
默認是沒有開啓AOF(append only file)方式持久化,可以通過appendonly參數啓用
appendonly true
目錄和RDB文件目錄一樣,默認文件名是appendonly.aof,可通過append filename參數修改:
appendfilename appendonly.aof
設置AOF文件的重寫
auto-aof-rewrite-percentage 100
當目前的AOF文件大小超過上一次重寫時的大少的百分之多少時會進行重寫,如果之前沒有重寫,則以啓動進的大小爲依據
auto-oaf-rewrite-min-size 60mb
限制允許重寫的最小AOF文件大小
BGREWRITEAOF命令手動執行AOF重寫
由於操作系統的緩存機制,數據並沒有立即寫入硬盤,而是進入了硬盤的緩存,默認系統每30秒會執行一次同步操作,以將緩存中的數據真正地寫入硬盤,在這30的過程中如果異常退出則會導制硬盤緩存中的數據丟失,設置同步的時機:
appendfsync everysec|always|no
everysec即每秒執行一次同步操作,always表示每次執行寫入都會執行同步,no表示交同操作系統來做即30秒一次。
Redis允許同時開始AOF和RDB,此時重啓Redis會使用AOF來恢復數據.
複製replication
在複製的概念中,數據庫爲爲兩類,主數據庫master和從數據庫slave,master可以進行讀寫操作,當寫操作會自動將數據同步給slave,而slave一般只讀,並接受master同步過來的數據。slave可以有多個,而只能擁有一個master。
Redis中使用slave,只需要在slave配置中加入”slaveof masterip:masterport”。
例:
$redis-server
默認監聽6379端口
$redis-server —port 6380 —slaveof 127.0.0.1 6379
此時在master中的任何數據變化都會自動地同步到slave中。
$redis-cli -p6379
$info replication
可以查看主從信息
通過設置slave的slave-read-only爲no使slave可讀寫,默認是中讀。但對slave的修改不會同步給任何其它數據庫,並且master中更新了對應的數據就會覆蓋slave的改動。
除了配置文件或命令行參數設置slaveof參數,還可以在運行時使用SLAVEOF命令修改。
$SLAVE 127.0.0.1 6379
slave還可以通過slaveof no one 命令使當前數據庫停止接收其它數據庫的同步,並轉換爲主數據庫。
min-slaves-to-write 3
表示只有當3個或以上的slaves連接到master,master纔是可寫的,否則會返回錯誤 “noreplicas not enough good slaves to write.”
min-slaves-max-lag 10
表示允許slave最長失去連接的時間,(即發送REPLCONF ACK命令)的時間小於這個值,則認爲slaves還在保持與master的連接。例:
master與3個slave相連,其中一個slave上一次與master聯繫是9秒前,這時master是可以寫入的,一旦10秒過後,該slave仍沒聯繫,則master認爲只有2個slaves,從而拒絕寫入數據。這一特性默認是關閉的。在分佈式中,打開併合理配置可以降低主從架構中因爲網絡分區導致的數據不一致問題。
slave也可以同時作爲master存在(master→slave(master)→slave)
通過複製可以實現讀寫分離。
Slave持久化
可以在master中禁用持久化 ,並在slave中開啓持久化,如果slave崩潰了,master會自動同步過來,但master崩潰後,手工通過slave 恢復數據時需要嚴格按照以下兩頻進行
在slave中使用SLAVEOF NO ONE命令將從數據庫提升成master繼續服務。
啓動之前崩潰的master,然後使用salveof命令將其設置成新的master的slave。
***當開啓複製且master關閉持久化功能時,一定不能使用Supervisor以及類似進程管理工具令master自動重啓。
同樣當master因故關閉時,也要避免直接重新啓動,因爲master重啓會因沒有持久化,所有數據都被清空了,這時slave依然會從master中同步數據。致使slave也被清空。
無硬盤複製
前面的複製都是基於RDB持久化實現
當master禁用RDB快照時(即刪除了所有的配置文件中的save語句),如果執行了複製初使化操作,Redis依然會生成RDB快照,所以下次啓動後master會以該快照恢復據。因爲複製的時間不確定,使得恢復的數據可能是在任何時間點的。
複製初使化時需要創建RDB快照文件,導致性能降低。
無硬盤複製選項,開啓該選項時,Redis在與slave進行復制初始化時將不會將快照內容存儲在硬盤上,而是直接通過網絡發送給slave。
repl-diskless-sync yes
增量複製
slave會存儲master的運行id,每個Redis運行實例都會擁有一個唯一的id,重啓後會生成一個新id.
在複製同步階段,master每將一個命令傳給salve時,都會把該命令存放在一個積壓隊列中,並記錄下當前積壓隊列中存入的命令的偏移量範圍。
slave接收到master傳來的命令時,會記錄下該偏移量。
主從連接準備就緒後,slave發送psync “PSYNC masterid 斷開前的偏移量”
master會判斷slave傳來的id是否正確
master判斷偏移量是否在積壓隊列中,如果存在執行增量複製,並將積壓隊列中相應的命令發送給slave,如果條件不符則會進行一次全部同步
repl-backlog-size 設置積壓隊列的大小,默認爲1M,積壓隊列越大,其允許的主從數據斷線的時間就越長。
repl-backlog-ttl 設置主從斷開連接後多久會釋放積壓的內存空間,默認是1 小時。
Sentinel哨兵
哨兵 監控Redis運午的狀況,是一個獨立的進程,監控master和slave是否運行正常,master出現故障時自動將slave轉換爲master
1.創建sentinel.conf配置文件,添加以下一行內容
sentinel monitor mymaster 127.0.0.1 6379 1其中mymaster 表示要監控的master的名字,可以自定義一個,大小寫字母,數字或“.-_”字符組成。後面兩個參數表示master的ip和端口號。最後的1表示最低通過票數
2.運行 $redis-sentinel /path/to/sentinel.conf
*哨兵監控一個系統,只需要配置其監控master即可,哨兵會自動發現所有slave。
*當master停止服務後,sentinel會選舉一個slave轉換會maste,並把原master轉換爲slave (當原master重新提供服務後就會是slave身份)
3.選舉優先規則 選擇優先級最高的slave,(通過slave-priority)來配置
複製命令偏移量越大越優先
運行id越小越優先
哨兵以獨立的進程方式對方從系統進行監控,一個哨兵可以監控多個主從系統,一個主從系統也可以設置多個哨兵sentinel
sentinel和主從數據庫建立連接後,sentinel 會定時執行下面3個操作
1.每10秒sentinel向master和slave發送ping 命令
2.每2秒sentinel向master和slave的_sentinel_:hello 頻道發送自己的信息
3.第1秒sentinel向master和slave和其它sentinel發送ping命令。
配置ping的時間間隔
大於1秒的會每一秒執行一次ping
sentinel down-after-milliseconds my master 60000
小於秒的會按配置的時間來發送ping
sentinel down-after-milliseconds my master 6000
如果超過down-after-milliseconds選項時間還沒有回覆,則sentinel認爲其主觀下線(subjective down +sdown)
sentinel 發送SENTINEL is-master-down-by-addr 命令詢問其它sentinel,
如果認爲下線達到指定數量時(大於前面配置的”sentinel monitor my master 127.0.0.1 6379 1”中的數量1),sentinel會認爲其客觀下線(objectively down +odown)
並選擇領頭的sentinel對主從系統發起故障恢復
sentinel 選舉規則
1.發現主數據庫客觀下線的節點向每個節點哨兵節點發送請求對方選自己成爲領頭sentinel
2.如果目標sentinel沒有選擇過別的節點,就會同意
3.如果有超過半數且超過quorum參數值的節點同意則選舉成功
4.如果多個sentinel同時參選出現沒有任何節點當選,剛隨機時間後重新選舉
*使用複製功能,總數據量的存儲量受限於內存最小的節點,形成木桶效應。
解決方案1.使用客戶端分片解決,即啓動多個 Redis數據庫節點,由客戶端決定哪個鍵存放在哪個節點。維護成本高,增加移除節點麻煩
解決方案1.使用集羣,集羣支持幾乎所有的單機實例支持的命令,對於涉及多鍵的命令(如MGET),如果每個鍵都位於一個節點中,則可以正常支持,否則會提示錯誤。除此之外,集羣只能使用默認的0號數據庫。如果執行select切換數據庫會報錯。
集羣
1.打開配置cluster-enabled啓用集羣功能,每個集羣中至少需要3個master才能正常運行
2.啓動多個redis獨立節點,集羣會將當前節點記錄的集羣狀態持久化地存儲在指定文件中,當前工作目錄下的nodes.conf文件。每個節點對應的文件必須同。
redis連接任意一個節點查看當前集羣狀態
3.INFO cluster
4.初使化集羣 redis-trib.rb create —replicas 1 ip:port ip:port ip:port [ip:port…]
create表示要初使化集羣, —replicas表示每個master擁有一個slave。redis-trib.rb會輸出集羣分配方案,如果同意輸入yes。
獲得集羣中節點信息
CLUSTER NODES
添加新節點,ip和port是集羣是任意節點的地址和端口 CLUSTER MEET ip port
Redis將每個鍵名的效部分使用 CRC16算法計算出散列值,然後對16384進行取取餘,使每個鍵都能分配到16384個插槽中,進行分配指定的節點處理。
鍵的有效部分是指
如果鍵名包含{符號,且在{符號後面存在}符號,並且{和}符號間至少有一個字符,則有效部分是指{和}之間的內容;
如果不滿足上一條規則,那麼整個鍵名爲有效部分
分配slot 如果slot之前沒被分配過可以採用
對點應節點執行,將指定slot分配給當前節點,如果slot分配過了就會報錯
CLUSTER ADD SLOT S
CLUSTER ADDSLOTS slot1 [slot2…]
例: CLUSTER ADDSLOTS 100 101
查看slot分配情況
CLUSTER SLOTS
將slot從127.0.0.1:6379移到127.0.0.1:6380
按提示執行後面步驟可完成slot的重分配
redis-trib.rb reshard 127.0.0.1:6379
-c參數支持集羣自動重定向,如果鍵不在該節點上,會自動重定請求,並返回結果,該過程對客戶端是透明的。 redis-cli -c -p 6379
如果一個至少負責一個 solt的master停止服務,且沒有相應的slave可以進行故障恢復,則整個集羣會進入下線狀態無未能繼續工作。
設置cluster-require-full-coverage no(默認爲yes)使集羣在該情況下仍能工作。
安全配置
參數指定Redis接受發送請求的地址。
bind 127.0.0.1
設置客戶端每次連接都需要發送密碼 requirepass password
如果master設置了密碼,slave中需要配置密碼
masterauth
將命令重命名 rename-commnad FLUSHALL newflushallcommandname
設置成空串,禁用該命令
rename-command FLUSHALL “”