Redis如何保證數據安全與性能保障

一、持久化

      Redis提供了兩種不同的持久化方法來將數據存儲到硬盤裏。一種叫快照(snapshotting),另一種叫只追加文件(append-only file,AOF) 。這兩種持久化方法可以同時使用,也可以單獨使用。

1.快照

    redis可以通過創建快照來獲得存儲在內存裏面的數據在某個時間點上的副本。

redis持久化配置

#RDB核心規則配置 save <指定時間間隔> <執行指定次數更新操作>,滿足條件就將內存中的數據同步到硬盤
中。官方出廠配置默認是 900秒內有1個更改,300秒內有10個更改以及60秒內有10000個更改,則將內存中的
數據快照寫入磁盤。若不想用RDB方案,可以用 save ""

save 60 10000

#當RDB持久化出現錯誤後,是否依然進行繼續進行工作,yes:不能進行工作,no:可以繼續進行工作,可以通
過info中的rdb_last_bgsave_status瞭解RDB持久化是否有錯誤
stop-writes-on-bgsave-error yes


#配置存儲至本地數據庫時是否壓縮數據,默認爲yes。Redis採用LZF壓縮方式,但佔用了一點CPU的時間。若關閉該選項,
但會導致數據庫文件變的巨大。建議開啓。
rdbcompression yes

#指定本地數據庫文件名,一般採用默認的 dump.rdb
dbfilename dump.rdb

#數據目錄,數據庫的寫入會在這個目錄。rdb、aof文件也會寫在這個目錄
dir /usr/local/redis/var

      根據配置,快照被寫入dbfilename選項的文件裏面。並存儲在dir目錄下,如果在新的快照文件創建完畢之前,Redis、系統或者硬件其中任意一個崩潰,那麼Redis將丟失最近一次創建快照之後寫入的所有數據。

創建快照的方法:

  1. 客戶端向redis發送BGSAVE命令,會建立子進程將快照寫入存儲,同時redis可以正常接收命令。

  2. 客戶端向redis發SAVE命令,redis在執行寫入存儲前不接收命令。

  3. 配置文件設置快照,例如save 60 5000,可配置多個。達到條件時觸發BGSAVE命令。

  4. SHUTDOWN時,會觸發SAVE命令。

  5. slave redis發關SYNC命令後,主啓動BGSAVE命令。

       如果系統發生崩潰,用戶將對視最近一次生成快照之後更改的所有數據。因此,快照快照持久化只適用於那些丟失一部分數據也不會造成問題的應用程序。

性能

       當Redis內存佔用量達到數十個GB,並且剩餘的空閒內存並不多,那麼執行BGSAVE可能會導致系統長時間地停頓,也可能引發系統大量地使用虛擬內存,從而導致Redis的性能降低至無法使用的程度。

      爲了防止Redis因爲創建子進程而出現停頓,我們可以考慮關閉自動保存,轉而通過手動發送BGSAVE或者SAVE進行之九華。SAVE命令會一直阻塞Redis而導致Redis停頓;並且因爲沒有子程序在正度資源,所以SAVE創建快照的速度會比BGSAVE創建快照的速度更快一些。

2.AOF持久化

    AOF持久化會將被執行的寫命令寫到AOF文件的末尾,以此來記錄數據發生的變化。Redis只要從頭到尾執行一次AOF文件包含的命令,就可以恢復AOF文件記錄的數據集。

持久化配置

#Redis 默認不開啓。它的出現是爲了彌補RDB的不足(數據的不一致性),所以它採用日誌的形式來記錄每個寫
操作,並追加到文件中。Redis 重啓的會根據日誌文件的內容將寫指令從前到後執行一次以完成數據的恢復工作
默認redis使用的是rdb方式持久化,這種方式在許多應用中已經足夠用了。但是redis如果中途宕機,會導致可
能有幾分鐘的數據丟失,根據save來策略進行持久化,Append Only File是另一種持久化方式,可以提供更好的
持久化特性。Redis會把每次寫入的數據在接收後都寫入 appendonly.aof 文件,每次啓動時Redis都會先把這
個文件的數據讀入內存裏,先忽略RDB文件。若開啓rdb則將no改爲yes
appendonly no


#aof持久化策略的配置
#no表示不執行fsync,由操作系統保證數據同步到磁盤,速度最快
#always表示每次寫入都執行fsync,以保證數據同步到磁盤
#everysec表示每秒執行一次fsync,可能會導致丟失這1s數據
#always請謹慎使用,這個選項讓Redis每次只寫入一個命令,可能會引發嚴重的寫入放大問題
#在某些情況下會導致固態硬盤壽命降低。
appendfsync everysec

 

# 在aof重寫或者寫入rdb文件的時候,會執行大量IO,此時對於everysec和always的aof模式來說,執行
fsync會造成阻塞過長時間,no-appendfsync-on-rewrite字段設置爲默認設置爲no。如果對延遲要求很高的
應用,這個字段可以設置爲yes,否則還是設置爲no,這樣對持久化特性來說這是更安全的選擇。設置爲yes表
示rewrite期間對新寫操作不fsync,暫時存在內存中,等rewrite完成後再寫入,默認爲no,建議yes。Linux的
默認fsync策略是30秒。可能丟失30秒數據
no-appendfsync-on-rewrite no
 

#aof自動重寫配置。當目前aof文件大小超過上一次重寫的aof文件大小的百分之多少進行重寫,即當aof文件
增長到一定大小的時候Redis能夠調用bgrewriteaof對日誌文件進行重寫。當前AOF文件大小是上次日誌重寫得
到AOF文件大小的二倍(設置爲100)時,自動啓動新的日誌重寫過程
auto-aof-rewrite-percentage 100
 

#設置允許重寫的最小aof文件大小,避免了達到約定百分比但尺寸仍然很小的情況還要重寫
auto-aof-rewrite-min-size 64mb


#數據目錄,數據庫的寫入會在這個目錄。rdb、aof文件也會寫在這個目錄
dir /usr/local/redis/var

       隨着Redis不斷運行,AOF文件體積也會不斷增加,爲了解決AOF文件不斷增大的問題,用戶可以發送BGREWRITEAOF命令,這個命令會通過移除AOF文件中的冗餘命令。

3.複製

       Redis可以使用一個主服務器(master)和多個從服務器(slave)發送更新,並使用從服務器處理所有讀請求,來實現自己的複製特性,並將其作爲擴展性能的一種手段。

配置

#從服務器 host主服務器的ip  port主服務器端口
slaveof host port

     從服務器在連接一個主服務器的時候,主服務器會創建一個快照文件並將其發送給從服務器。

步驟:

主服務器 從服務器
(等待命令進入) 連接(或者重連接)主服務器,發送SYNC命令
開始執行BGSAVE,並使用緩衝區記錄BGSAVE之後執行的所有命令 根據配置項來決定是繼續使用現有的都數據(如果有的話)來處理客戶端的命令請求,還是向發送請求的客戶端返回錯誤
BGSAVE執行完畢,向從服務器發送快照文件,並在發送期間繼續使用緩衝區記錄被執行的寫命令 丟棄返回舊數據(如果有的話),開始載入主服務器發來的快照文件
快照文件發送完畢,開始向從服務器發送存儲在緩衝區裏面的寫命令 完成對快照文件的解釋操作,像往常一樣開始接受命令請求
緩衝區存儲的寫命令發送完畢;從現在開始每執行一個寫命令,就向從服務器發送相同的寫命令 執行主服務器發來的所有存儲在緩衝區裏面的寫命令;並從現在開始,接受並執行主服務器傳來的每個寫命令

        從服務器在同步時,會清空自己的所有數據。

主從服務器--哨兵模式文章推薦:https://www.jianshu.com/p/06ab9daf921d

4.驗證持久化文件

     如果遇到系統故障時進行數據恢復的工具。Redis提供了兩個命令行程序redis-check-aof和redis-check-dump,他們可以檢查文件的狀態,並在有需要的情況下對文件進行修復。

5.事務

     所謂事務(Transaction) ,是指作爲單個邏輯工作單元執行的一系列操作。事務必須滿足ACID原則(原子性、一致性、隔離性和持久性)。簡單來說事務其實就是打包一組操作(或者命令)作爲一個整體,在事務處理時將順序執行這些操作,並返回結果,如果其中任何一個環節出錯,所有的操作將被回滾。

第一步鍵入MULTI命令標識事務的開始

第二步執行業務邏輯

第三部 exec執行/DISCARD回滾

需要注意的是:

1.Redis的事務沒有關係數據庫事務提供的回滾(rollback),所以開發者必須在事務執行失敗後進行後續的處理;

2.如果在一個事務中的命令出現錯誤,那麼所有的命令都不會執行;

3.如果在一個事務中出現運行錯誤,那麼正確的命令會被執行。

WATCH

研究過java的J.U.C包的人應該都知道CAS,CAS是一種保證原子性的操作。那麼redis也提供了這樣的一個機制,就是利用watch命令來實現的。

WATCH命令可以監控一個或多個鍵,一旦其中有一個鍵被修改(或刪除),之後的事務就不會執行,監控一直持續到EXEC命令。

6.非事務性流水線

       使用事務的其中一個好處就是底層的客戶端會通過使用流水線來提高事務執行時的性能。使用非事務型流水線(non-transactional pipeline)同樣可以獲得相似的性能提升,並且可以讓用戶同時執行多個不同的命令。

       MULTI和EXEC也會消耗資源,並且可能會導致其他重要的命令被延遲執行。但也可以在不使用MULTI和EXEC的情況下,獲得流水線帶來的所有好處。

pipe = conn.pipeline()

       在執行pipeline()時傳入True作爲參數,或者不傳入任何參數,那麼客戶端將使用MULTI和EXEC包裹起用戶要執行的所有命令。如果傳入False爲參數,那麼客戶端同樣會像執行事務那樣收集用戶要執行的所有命令,只是不再使用MULTI和EXEC包裹這些命令。如果用戶需要向Redis發送多個命令,並且對於這些命令來說,一個命令的執行結果並不會影響另一個命令的輸入,而且這些命令也不需要以事務的方式來執行的話,那麼我們可以通過向pipeline()方法傳入False來進一步提升Redis的整體性能。

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