1. 程式人生 > 其它 >Redis-持久化、主從、哨兵及叢集架構

Redis-持久化、主從、哨兵及叢集架構

Redis持久化

RDB快照

預設情況下,Redis將記憶體資料庫快照儲存在名字為dump.rdb的二進位制檔案中。 你可以對Redis進行設定,讓它在“N秒內資料至少有M個改動”這一條件被滿足時,自動儲存一次資料集。 比如說,以下設定會讓Redis在滿足“60秒內有至少有1000個鍵被改動”這一條件時,自動儲存一次資料庫集。
save 60 1000 
  還可以手動執行命令生成RDB快照,進入redis客戶端執行命令save和bgsave可以生成dump.rdb檔案,每次命令執行都會將所有redis記憶體快照到一個新的rdb檔案裡,並覆蓋原有rdb快照檔案。

bgsave的寫時複製(COW)機制

  Redis藉助作業系統提供的寫時複製技術(Copy-On-Write,COW),在生成快照的同時,依然可以正常處理寫命令。簡單來說,bgsave子程序是由主執行緒fork生成的,可以共享主執行緒的所有記憶體資料。bgsave子程序和bgsave子程序互相不影響。但是,如果主執行緒要修改一塊資料,那麼,這塊資料就會被複制一份,生成該資料的副本。然後,bgsave子程序會把這個副本資料寫入RDB檔案,而在這個過程中,主執行緒依然可以直接修改原來的資料。 save與bgsave
命令 save bgsave
IO型別 同步 非同步
是否阻塞redis其他命令 否(在生成子程序執行呼叫fork函式時會有短暫阻塞)
複雜度 O(n) O(n)
優點 不會消耗額外記憶體 不阻塞客戶端命令
缺點 阻塞客戶端命令 需要fork子程序,消耗記憶體

AOF(append-only file)

  快照功能並不是非常耐久(durable):如果Redis因為某些原因而造成故障停機,那麼伺服器將丟失最近寫入、且仍未儲存到快照的那些資料。從1.1版本開始,Redis增加了一種完全耐久的持久化方式:AOF持久化,將修改的每一條指令記錄進檔案appendonly.aof(先寫入os cache,每隔一段時間fsync到磁碟)。 你可以通過修改配置檔案來開啟AOF功能:
#appendonly yes

  

  從現在開始,每當Redis執行一個改變資料集的命令時(比如SET),這個命令就會被追加到AOF檔案的末尾。   這樣的話,當Redis重新啟動時,程式就可以通過重新執行AOF檔案中的命令來達到重建資料集的目的。   你可以配置Redis多久才將資料fsync到磁碟一次。   有三個選項:
appendfsync always:每次有新命令追加到AOF檔案時就執行一次fsync,非常慢,也非常安全 
appendfsync everysec:每秒fsync一次,足夠快,並且在故障時只會丟失1秒的資料 
appendfsync no:從不fsync,將資料交給作業系統來處理。更快,也更不安全的選擇。

  推薦的措施為everysec,可兼顧速度和安全性。

AOF重寫

  AOF檔案裡可能有太多沒用的指令,所以AOF會定期根據記憶體的最新資料生成aof檔案。   例如,執行了如下命令:
127.0.0.1:6379> incr readcount
(integer) 1
127.0.0.1:6379> incr readcount
(integer) 2
127.0.0.1:6379> incr readcount
(integer) 3
127.0.0.1:6379> incr readcount
(integer) 4
127.0.0.1:6379> incr readcount
(integer) 5

  重寫AOF檔案裡變成:

*3
$3
SET
$2
readcount
$1
5

  如下兩個配置可以控制AOF自動重寫頻率:

#aof檔案至少要達到64M才會自動重寫,檔案太小恢復速度本來就快,重寫意義不大
#auto-aof-rewrite-min-size 64mb

#aof檔案自動上一次重寫後文件大小增長了100%則再次觸發重寫
#aof-aof-rewrite-percentage 100

  當然,AOF還可以手動重寫,進入redis客戶端執行命令bgrewriteaof重寫AOF。

  注意:AOF重寫redis會fork出一個子程序去做(與bgsave命令類似),不會對redis正常命令處理有太多的影響。

RDB與AOF的選擇

命令 RDB AOF
啟動優先順序
體積
恢復速度
資料安全性 容易丟資料 根據策略決定

  生產環境都可以啟用,redis啟動時如果既有rdb檔案又有aof檔案則會優先選擇aof檔案恢復資料,因為aof一般來說資料更安全一點。

Redis4.0混合持久化

  重啟Redis時,我們很少使用RDB來恢復記憶體狀態,因為會丟失大量資料。我們通常使用AOF重放,但是重放AOF日誌效能相對RDB來說要慢很多,這樣在Redis示例很大的情況下,啟動需要花費很長的時間。Redis4.0為了解決這個問題,帶來了一個新的持久化選項——混合持久化。

  通過如下配置可以開啟混合持久化(必須先開啟AOF):

# aof-use-rdb-preamble yes

  如果開啟了混合持久化,AOF在重寫時,不再是單純的將記憶體資料轉換為RESP命令寫入AOF檔案,而是將重寫這一刻之前的記憶體做RDB快照處理,並且將RDB快照內容和增量的AOF修改記憶體資料的命令存在一起,都寫入新的AOF檔案,新的檔案一開始不叫appendonly.aof,等到重寫完新的AOF檔案才會進行改名,覆蓋原有的AOF檔案,完成新舊兩個AOF檔案的替換。

  於是Redis重啟的時候,可以先載入RDB的內容,然後再重放增量AOF日誌就可以完全替代之前的AOF全量檔案重放,因此重啟效率大幅得到提升。

Redis資料備份策略

  • 寫crontab定時排程指令碼,每小時都copy一份rdb或aof的備份到一個目錄中去,僅僅保留最近48小時的備份。
  • 每天都儲存一份當日的資料備份到一個目錄中去,可以保留近1個月的備份。
  • 每天晚上將當前機器聲的備份複製到其他機器上,以防機器損壞。

Redis主從架構

Redis主從工作原理

  如果你為master配置了一個slave,不管這個slave是否是第一次連線上Master,他都會發送一個PSYNC命令給master請求複製資料。master收到PSYNC命令後,會在後臺進行資料持久化通過bgsave生成最新的rdb快照檔案,持久化期間,master會繼續接收客戶端的請求,它會把這些可能修改資料集的請求快取在記憶體中。當持久化進行完畢後,master會把這份rdb檔案資料集傳送給slave,slave會把接收到的資料進行持久化生成rdb,然後再載入到記憶體中。然後,master再將之前快取在記憶體中的命令傳送給slave。

  當master與slave之間的連線由於某些原因而斷開時,slave能夠自動重連master,如果master收到了多個slave併發連線請求,它只會進行一次持久化,而不是一個連線一次,然後再把這一份持久化的資料傳送給多個併發連線的salve。

  如果有很多從節點,為了緩解主從複製風暴(多個從節點同時複製主節點導致主節點壓力過大),可以做如下架構,讓部分從節點與從節點(與主節點同步)同步資料。

主從複製流程圖:

全量複製

部分複製

管道(Pipeline)

  客戶端可以一次性發送多個請求而不用等待伺服器的響應,待所有命令都發送完後再一次性讀取服務的響應,這樣可以極大的降低多條命令執行的網路傳輸開銷,管道執行多條命令的網路開銷實際上只相當於一次命令執行的網路開銷。需要注意到是用pipiline方式打包命令傳送,redis必須在處理完所有命令先前快取起所有命令的處理結果。打包的命令越多,快取消耗記憶體也越多。所以並不是打包的命令越多越好。

  pipeline中傳送的每個command都會被server立即執行,如果執行失敗,將會在此後的響應中得到資訊;也就是pipeline並不是表達“所有command都一起成功”的語義,管道中命令失敗,後面命令不會有影響,繼續執行。