寫給Java程序員看的Redis教程-------第四章.Redis的數據安全於性能保障

在之前的文章中,我們應該瞭解到了:Redis是一個基於內存的數據庫。基於內存帶給Redis非常快的速度,但是內存的數據將在關機斷電後消失,而這一章就是了解Redis如何將自己的數據存儲到硬盤上,從而提高系統的可靠性。

1. 持久化

Redis提供了兩種持久化的方案。

  1. RDB,RedisDataBase,以文件方式存儲Redis數據庫中的內容。
  2. AOF,AppendOnlyFile,以文件方式存儲Redis數據庫所有寫的命令。

這兩種方法互不影響,可以同時使用,也可以單獨使用或者都不使用(這種情況就要考慮好Redis的作用)。

這兩組配置都在redis.conf中,這裏複製一份默認配置,僅供參考。

############################## MEMORY MANAGEMENT ################################
# rdb的觸發條件,前者是秒,後者是在指定時間內的寫命令條數
# 如 900 1,就是每900秒有一條寫命令,那麼進行rdb存儲。
save 900 1
save 300 10
save 60 10000

# rdb的一些配置
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes

# rdb的文件名和文件所在目錄
dbfilename dump.rdb
dir ./

############################## APPEND ONLY MODE ###############################
# aof 默認是關閉的
appendonly no

# aof文件名: "appendonly.aof"
appendfilename "appendonly.aof"

# 還有兩個選項: always,no
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble no

1.1. RDB,快照文件存儲Redis內容

​ RDB是redis默認的持久化方案,redis會將某個時間點上的數據進行一個快照,然後將快照以文件方式保存在磁盤中,當需要時來讀取快照文件恢復數據。

​ 例子:我們設定的條件爲每天只要有一個寫命令,那麼進行rdb操作。

​ 當某一天服務器突然斷電,我們就可以通過讀取rdb快照,恢復到斷電前最近一次保存的狀態,而快照之後的數據就丟失了。如果你的應用對redis的架構是DB,那麼丟失一天的數據是無法忍受的;如果你僅僅將其當作一個緩存,那麼丟失一天的數據是完全可以接受的。所以rdb的設置應該按照應用的需求來設置。

觸發rdb的條件

  • 客戶端向Redis發送一條命令:BGSAVE。redis會創建一個子進程,子進程負責將快照寫入硬盤,而父進程繼續處理命令請求。
  • 客戶端向Redis發送一條命令:SAVE。redis會阻塞所有命令,執行快照操作,直到操作完成。很明顯SAVE命令會大大快於BGSAVE命令,但是會造成較長時間的阻塞。
  • 用戶設置了save配置選項,如:save 60 1。每六十秒只要有一條寫命令,redis會進行BGSAVE操作。
  • Redis受到一條SHUTDOWN命令是,或者接收到標準TERM信號時,會執行一個SAVE命令,執行完畢後關閉Redis。
  • 當一臺Redis連接上另一個Redis,並要求複製其內容時(SYNC命令),如果主Redis沒有正在執行BGSAVE,或者沒有剛剛接手BGSAVE操作,那麼主服務器也會執行一條BGSAVE命令。

考慮是否使用rdb快照

  1. 當redis中的數據十分重要時,不允許存在丟失時,我們不應該使用rdb快照,因爲其大概率會丟失數據。
  2. 用戶能否忍受快照造成的卡頓,當redis過大時,rdb快照將會造成以分鐘記得卡頓,如果用戶無法容忍,請不要使用rdb。
  3. 當你把redis僅作緩存時,當你進行小型開發時,能夠容忍數據丟失時,使用rdb是一個不錯得選擇。

1.2 AOF持久化

​ aof全程Append-Only File,即添加到文件尾部;

​ aof持久化會將被執行的寫命令寫到aof文件得末尾,以此來記錄數據發生的變化。當需要恢復數據時,redis挨個執行aof文件中的命令即可。

​ aof默認是關閉的,我們需要手動打開,打開你的redis.conf進行如下操作。

# aof 默認是關閉的,我們將其改爲yes 後重啓redis服務。
appendonly yes

​ 重啓redis之後,redis服務器端執行的寫命令將會被寫入aof文件的尾部(aof)。

當執行一條命令後,redis寫入文件將會被操作系統分爲若干步

  1. 將寫入內容放入緩存中
  2. 操作系統認爲緩存已滿,將緩存刷入文件中。

當然用戶可以命令操作系統將文件同步到硬盤,同步操作會一直阻塞直到指定的文件被寫入硬盤爲止。

​ aof同步命令是可以配置的,選擇其同步時機。

選項 同步頻率
always 每個寫命令都套同步寫入硬盤,嚴重降低Redis的速度
everysec 每秒執行一次同步,顯式地將多個寫命令同步到硬盤(推薦)
no 讓操作系統來決定應該何時同步

​ 選擇always的話,當系統崩潰時丟失數據最少,不過遺憾的是機械磁盤在這種情況每秒只能處理大約200個寫命令,固態每秒也只能幾萬個寫命令(固態壽命與寫次數相關,寫得越多死的越快)。

​ everysec則是每秒一次,當系統崩潰時,最多丟失一秒的數據。此外,當硬盤忙於寫操作時,Redis還會放慢自己的速度一遍適應硬盤的最大寫入速度。

​ no,你不願意把丟失的數據量交給操作系統的,相信我。此外,當緩衝區被等待寫入硬盤的數據填滿時,Redis的寫入操作將被阻塞,並導致Redis處理命令的速度變慢。 總之不建議你使用,這裏只爲了介紹三個可選項而已。

AOF的缺陷:AOF的文件大小

AOF能夠保證丟失少量數據(可能最多就一秒的數據),又不會造成卡頓,那麼爲什麼默認是rdb呢?

請看以下這些redis命令。

[root@VM_0_15_centos redis-4.0.2]# redis-cli 
127.0.0.1:6379> set a b
OK
127.0.0.1:6379> set a c
OK
127.0.0.1:6379> set a d
OK
127.0.0.1:6379> set a c
OK
127.0.0.1:6379> set a b
OK
127.0.0.1:6379> set a a
OK
127.0.0.1:6379> del a
(integer)1

這六條命令對redis的影響僅僅是改變a->b爲沒有.可是AOF會如實記錄這七條命令。

如果更誇張呢?對於一個系統來說,頻繁的更新是很有可能的,插入後刪除的需求也很大。總而言之,無效操作的數量太多了。這必將導致AOF文件的臃腫。

redis提供的解決方案是:BGREWRITEAOF命令,當用戶執行此命令時,redis會rewrite(重寫)AOF文件,將AOF中冗餘的命令刪去,使其儘可能的小。

BGREWRITEAOF命令也可以通過配置觸發:

# 默認配置:當增加了100%的大小時
auto-aof-rewrite-percentage 100
# 默認配置:當文件體積大於64MB時
auto-aof-rewrite-min-size 64mb

2. 複製

將Redis持久化是很有必要的,而隨着負載量的上升,或者數據的完整性越來越重要是,用戶可能需要使用複製特性。

關係數據庫通常會使用一個主服務器向多個從服務器發送更新,並使用從服務器來處理所有讀請求。Redis也是用了同樣的方法來實現自己的複製特性。

2.1 對Redis的複製相關選項進行配置

當從服務器連接主服務器的時候,主服務器會執行BGSAVE操作。而BGSAVE操作,我們在第一部分已經講過,不再提了。

而對於從服務器,所必須的選項只有savleof。

如果用戶在啓動Redis服務器的時候,制定了一個包含 slaveof host port選項的配置文件,那麼Redis服務器將根據該選項給定的 IP 地址和端口號來連接主服務器。

對於一個正在運行的從服務器,用戶可以使用SLAVEOF no one 命令來讓服務器種植複製操作。

也可以使用SAVLEOF host port來重選一個主服務器。

2.2Redis複製的啓動過程

步驟 主服務器操作 從服務器操作
1 (等待命令進入) 連接(重連)主服務器,發送SYNC命令
2 開始執行BGSAVE,並使用緩衝區記錄BGSAVE之後的所有寫命令 此時客戶端對從服務器的請求,將被報錯,也有可能仍返回舊數據
3 BGSAVE執行完畢,發送快照給從服務器,發送的同時,執行之前緩衝的寫命令 丟棄所有舊數據,載入接收到的快照文件
4 快照發送完畢,開始向從服務器發送存儲在緩衝區裏的寫命令。 完成快照同步,開始接受主服務器的寫命令
5 每執行一個寫命令,發送一個相同的命令 接受主服務器的寫命令

在第二步,我們可以看到Redis在執行BGSAVE時,需要緩衝區,所以我們建議主服務器只是用50%~60%的內存,剩餘內存留作BGSAVE操作和寫命令的緩衝區。

2.3 主從鏈

當讀請求重要性明心高於寫請求的重要性,並且讀請求的數量遠超出一臺Redis服務器可以處理的封你爲時,用戶需要不斷增加從服務器,而隨着從服務器的增加,主服務器可能無法快速地更新所有從服務器,或者因爲重連和重新同步導致系統超載。那麼我們就可以使用主從鏈。

主從鏈如圖所示。

在這裏插入圖片描述

3. 處理系統故障

即使軟件和硬件都完美無缺,Redis系統仍有可能遇到注入斷電,地震等不可抗力導致的災難。

3.1 驗證快照和AOF文件

無論是RDB還是AOF,都提供了在遇到系統故障時進行數據回覆的工具。

Redis提供了兩個命令程序,其可以在系統故障發生之後,檢查AOF文件和快照文件的狀態,並在有需要的情況下對文件進行修復。

[root@VM_0_15_centos etc]# redis-check-aof 
Usage: redis-check-aof [--fix] <file.aof>
[root@VM_0_15_centos etc]# redis-check-rdb 
Usage: redis-check-rdb <rdb-file-name>

redis-check-aof

當你運行這個命令時,給定了–fix 參數,那麼程序將對AOF文件進行修復,修復方法很簡單:

掃描給定的AOF文件,尋找不正確或者不完整的命令,當發現第一個出錯命令的時候,程序會刪除之後的所有命令(含出錯命令)。在大多數情況下,被刪除的都是AOF文件末尾的不完整的寫命令。

redis-check-rdb

目前並沒有辦法修復出錯的快照文件。原因在於快照文件本身經過了壓縮,導致錯誤可能是分佈在各個地方,無法統一處理。因此建議爲重要的快照保留多個備份,並進行驗證。

3.2 更換故障主服務器

當主服務器出現故障時,我們可以通過SAVE命令得到一個快照,依次將數據遷移到另一臺Redis服務器上,達到更換主服務器的目標。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章