redis持久化與可用性
redis對于持久化有快照及aof日志文件兩種形式。
快照db文件,優點是二進制,大小比aof日志文件小。但會丟失最后一次成功備份時間到down機時間的數據。
aof相比而言文件大小就大了點,但相對快照來講,不大容易丟失文件。
目前redis檢查數據文件是否有錯對于快照及aof都能夠支持,但修復則只對aof文件有效。
快照文件每次備份都是全量備份,原理是先fork出一個子進程,父子進程共享數據域。接著子進程開始將共享數據域中的數據寫入到一個臨時文件,寫完之后原子性的替換掉原先的備份db文件。如果在備份過程中,有新的寫請求進來,這時創建一個當前寫請求對應數據的副本頁面,新的寫請求更新在副本頁上。這就是 copy-on-write。這種方式當文件特別大時,不至于把內存撐爆。
快照文件可以用bgsave及save來進行觸發,當然也可以配置每多少秒有多少寫請求就觸發備份,如 配置 save 100 1000 表示在100秒中有1000次寫就觸發備份。
aof文件,是追加式的加入到aof未尾。每次redis接收到寫請求都會先寫入到內存中的buffer中,然后刷新到磁盤文件中。什么時刷新到磁盤文件中可以用appendfsync來進行配置。
appendfsync的值可以是always,second,no。always表示寫請求進來時,馬上把數據寫到磁盤,這種方式當大量寫請求時會造成磁盤等待。second表示每秒中操作系統將buffer中的數據寫到磁盤。no,表明完全由操作系統控制寫入到磁盤的時間(這比較危險,不知道會失多少數據)。
實際項目中用aof文件,定期做整理,aofrewrite,可以配置當aof文件增加多少倍或者達到最小大小時進行整理。
前面是持久化內容,考慮如果讀請求很大,單臺redis無法提供高性能服務時。這時可以使用主/備服務,主redis負責接收寫請求與讀請求,并將寫請求同步到從redis。從redis只可讀。
主/從redis同步數據,原理比較簡單,步聚如下:
1.從redis發送一個sync命令給主master (從redis可以對外接受讀請求,也可以不接受)
2.主master執行一個bgsave,生成最新的備份文件,這個過程中如果有新的寫請求則將它寫入到backlog。
3.當主master生成最新備份db文件后,主master將它發送到從redis服務器
4. 從redis服務器接收完備份文件后,替換掉原從redis內存中的數據,然后ack給主master
5.主master最后將接受sync請求并且開始做bgsave起到從redis發回ack后這段時間的所有數據backlog發回到從redis
6.從redis解析backlog,并放入到內存當中
實踐過程中發現,當主/從進行同步時,主redis必定會生成一個最新的db后綴的備份文件。而aof文件則是只有當主master配置了appendonly為yes時這會
產生。假如主redis下同時存在aof和db備份文件,這時根據從redis是否支持aof來決定是否同步aof文件。
還有一點需要特別注意的是,每次從slave重啟,那同步的數據文件是主master下整個文件。
關于這點,可以自己實現解析aof文件來實現增量同步。
故障恢復:
主redis為 10.45.9.114,端口6001
從redis為 10.45.9.111,端口為6002
當主master掛了時,選擇slave做為主master,命令如下:
在slave上執行:
bgsave,并執行 slaveof no one
這里的slaveof no one不會序列化到配置文件,重啟后還是以配置文件中的設置為準
之后更新客戶端,使其指向新的master,即10.45.9.111這臺redis
master 10.45.9.114恢復后,將其做為新master的slave
這時查看數據文件是否損壞,這里用的是aof備份,因此使用命令:
./redis-check-aof /home/jbossas/Data/redis/redis-data/appendonly.aof
結果如下:
AOF analyzed: size=245, ok_up_to=245, diff=0
AOF is valid
如果aof文件損壞的壞,則需要使用以下命令來恢復:
./redis-check-aof --fix /home/jbossas/Data/redis/redis-data/appendonly.aof
之后設置10.45.9.114這臺機子的redis配置文件 slaveof為 slaveof 10.45.9.111 6002
之后重啟即可
redis優化
減少內存,redis在對以下集合:
ZSETS,LISTS,HASHS
當它們的元素數量及value大小小于某個限值時,會用zipList(數組)來減少內存存儲
設置參數:
list-max-ziplist-entries 512
list-max-ziplist-value 64
對于SETS也當元素個數小于某個限值時,也會存儲成一個數組,intSet
設置參數:
set-max-intset-entries 512
對于原有的集合,redis存儲數據時會比較占空間。
如list集合,redis采用一個鏈表來存
每個結點存儲一個數據,而這個結點需要額外的三個指針。這三個指針分別指向前結點,后結點以及當前數據域