Redis系列(四):Redis持久化和主從複製原理
一、持久化
所謂的持久化就是把記憶體中的資料寫到磁碟中去,防止服務宕機後記憶體資料丟失。Redis4.0之前提供了兩種持久化方式:RDB(預設) 和AOF,Redis4.x之後新增了一種混合持久化(本文所用的Redis版本是redis‐5.0.2)
1、RDB
RDB是Redis Database縮寫,在預設情況下,Redis將記憶體資料庫快照儲存在名字為dump.rdb的二進位制檔案中。可以對Redis進行設定,讓它在“ N秒內至少有M個鍵值改動”這一條件被滿足時,自動儲存一次資料。比如下圖,900秒內有1個鍵值或者300秒內有10個鍵值或者60秒內有10000個鍵值改動,自動儲存一次資料;關閉RDB只需要將所有的save儲存策略註釋掉即可。
還可以手動執行命令生成RDB快照,進入Redis客戶端執行命令save或bgsave可以生成dump.rdb檔案,每次命令執行都會將所有Redis記憶體快照到一個新的rdb檔案裡,並覆蓋原有rdb快照檔案。save是同步命令,bgsave是非同步命令,bgsave會從redis主程序fork(fork()是linux函式)出一個子程序專門用來生成rdb快照檔案。Redis配置自動生成rdb檔案後臺使用的是bgsave方式。
命令 | save | bgsave |
IO型別 | 同步 | 非同步 |
是否阻塞redis其它命令 | 是 | 否(在生成子程序執行呼叫fork函式時會短暫阻塞) |
複雜度 | O(n) | O(n) |
優點 | 不會消耗額外記憶體 | 不阻塞客戶端命令 |
缺點 | 阻塞客戶端命令 | 需要fork子程序,消耗記憶體 |
2、AOF
AOF是append-only file縮寫,RDB快照並不是非常耐久(durable):如果Redis因為某些原因而造成故障停機,那麼伺服器將丟失最近寫入、且仍未儲存到快照中的那些資料。從Redis1.1版本開始,Redis增加了一種完全耐久的持久化方式:AOF持久化。可以通過修改如下配置檔案來開啟AOF功能:
修改了配置檔案,先執行bin/redis-cli shutdown停止Redis,然後執行bin/redis-server redis.conf啟動Redis,此時appendonly生效;從現在開始, 每當Redis執行一個改變鍵值的命令時(比如 SET),這個命令就會被追加到AOF檔案的末尾。這樣的話,當 Redis重新啟動時,程式就可以通過重新執行AOF檔案中的命令來達到重建資料的目的。你可以配置 Redis 多久才將資料 fsync到磁碟一次。
① appendfsync always:每次有新命令追加到AOF檔案時就執行一次fsync,非常慢,也非常安全。
② appendfsync everysec:每秒fsync一次,足夠快(和使用 RDB 持久化差不多),並且在故障時只會丟失 1 秒鐘的資料。
③ appendfsync no:從不 fsync,將資料交給作業系統來處理。更快,也更不安全的選擇。
推薦(並且也是預設)的措施為每秒fsync一次,這種fsync策略可以兼顧速度和安全性。配置檔案如下:
執行如下命令:
(1)啟動客戶端,連線Redis bin/redis-cli 並執行set toby xu
(2) 到dir(redis.conf這個配置檔案裡面的資料持久化的目錄屬性)所在的目錄下檢視,如下圖:
(3)vim appendonly.aof,檔案的內容在後面的RESP(Redis序列化協議)中詳解講解,Redis序列化協議官網地址:https://redis.io/topics/protocol
AOF重寫:
(1)AOF檔案裡可能有太多沒用指令,所以AOF會定期根據記憶體的最新資料生成新的aof檔案,當然可以手工執行bgrewriteaof命令也能重寫AOF,比如執行如下命令:
(2)重寫後AOF檔案裡變成:
如下兩個配置可以控制AOF自動重寫頻率:
① auto-aof-rewrite-min-size 64mb :aof檔案至少要達到64M才會自動重寫。
② auto-aof-rewrite-percentage 100 :aof檔案自上一次重寫後文件大小增長了100%則再次觸發重寫。
當然AOF還可以手動重寫,進入redis客戶端執行如上圖命令bgrewriteaof重寫AOF注意,AOF重寫Redis會fork出一個子程序去做,不會對Redis正常命令處理有太多影響。
3、RDB和AOF對比
Redis啟動時如果既有RDB檔案又有AOF檔案則優先選擇AOF檔案恢復資料,因為AOF一般來說資料更全一點。
持久化方式 | RDB | AOF |
啟動優先順序 | 低 | 高 |
檔案大小 | 小 | 大 |
恢復速度 | 快 | 慢 |
資料安全性 | 容易丟資料 | 根據策略決定 |
4、Redis4.0混合持久化
重啟Redis時,我們很少使用 RDB來恢復記憶體狀態,因為會丟失大量資料。我們通常使用AOF日誌重放,但是重放AOF日誌效能相對RDB來說要慢很多,這樣在 Redis 例項很大的情況下,啟動需要花費很長的時間。 Redis4.0為了解決這個問題,帶來了一個新的持久化選項——混合持久化。配置如下:
如果開啟了混合持久化,AOF在重寫時,不再是單純將記憶體資料轉換為RESP命令寫入AOF檔案,而是將重寫這一刻之前的記憶體做RDB快照處理,並且將RDB快照內容和增量的AOF修改記憶體資料的命令存在一起,都寫入新的AOF檔案,新的檔案一開始不叫appendonly.aof,等到重寫完新的AOF檔案才會進行改名,原子的覆蓋原有的AOF檔案,完成新舊兩個AOF檔案的替換。於是在Redis重啟的時候,可以先載入RDB的內容,然後再重放增量AOF檔案就可以完全替代之前的AOF全量檔案重放,因此重啟效率大幅得到提升。
二、Redis主從
1、主從複製概念
主從複製,是指將一臺Redis伺服器的資料,複製到其他的Redis伺服器。前者稱為主節點(master),後者稱為從節點(slave),資料的複製是單向的,只能由主節點到從節點。
2、主從複製的原理
(1)全量複製
將主節點中的所有資料都發送給從節點,是一個非常重型的操作,當資料量較大時,會對主從節點和網路造成很大的開銷。全量複製流程圖如下:
① slave會發出一個同步命令,剛開始是Psync命令,表示要求master主機同步資料
② master收到psync命令後,會通過執行bgsave生成最新的RDB快照檔案,持久化期間,master會繼續接收客戶端的請求,它會把寫請求快取在記憶體中
③ 傳送RDB檔案給slave
④ master再將之前快取在記憶體中的命令傳送給slave
⑤ 重新整理舊的資料。slave在載入主節點的資料之前要先將老資料清除
⑥ 載入RDB檔案將資料庫狀態更新至主節點執行bgsave時的資料庫狀態和緩衝區資料的載入
⑦ master同步長連線持續把寫命令傳送給slave,以保證資料的一致
(2)部分複製
部分複製是Redis 2.8以後出現的,用於處理在主從複製中因網路閃斷等原因造成的資料丟失場景,當slave再次連上master後,如果條件允許,master會補發丟失資料給slave。因為補發的資料遠遠小於全量資料,可以有效避免全量複製的過高開銷。部分複製流程圖如下:
① 如果網路抖動(連線斷開 connection lost)
② master還是會寫repl_back_buffer(複製緩衝區)
③ slave會繼續嘗試連線主機
④ slave會把自己當前run_id和偏移量傳輸給master,並且執行pysnc命令同步
⑤ slave傳送過來的offset在repl_back_buffer中,則master會將快取中從offset以後的資料一次性同步給slave,否則全量複製
⑥ master同步長連線持續把寫命令傳送給slave,以保證資料的一致
3、主從搭建
其中slave的主要配置如下:
port 6380 pidfile /var/run/redis_6380.pid dir /usr/local/redis-5.0.2/6380 replicaof 192.168.160.146 6379 replica-serve-stale-data yes replica-read-only yes
(1)在6379 set toby xu
(2)在6380 keys *
至此Redis主從搭建完成!!!!!