學習筆記——Redis
-
Redis簡介
Redis是基於記憶體的高效能key-value資料庫,整個資料庫統統載入在記憶體當中進行操作,定期通過非同步操作把資料庫資料flush到硬碟上進行儲存。因為是純記憶體操作,Redis的效能非常出色,每秒可以處理超過 10萬次讀寫操作,是已知效能最快的Key-Value DB。預設有16個數據庫。Redis是單程序單執行緒的,Redis利用佇列技術將併發訪問變為序列訪問,消除了傳統資料庫序列控制的開銷。
Redis的日誌級別有四種(redis在預設情況下,是不會生成日誌檔案的,所以需要配置)
- debug:會打印出很多資訊,適用於開發和測試階段
- verbose(冗長的):包含很多不太有用的資訊,但比debug要清爽一些
- notice:適用於生產模式
- warning : 警告資訊
配置檔案
maxmemory_policy:記憶體清除策略,Redis在佔用的記憶體超過指定的maxmemory之後,會自動根據策略來清除記憶體。
- volatile-lru(least recently used):最近最少使用演算法,從設定了過期時間的鍵中選擇空轉時間最長的鍵值對清除掉;
- volatile-lfu(least frequently used):最近最不經常使用演算法,從設定了過期時間的鍵中選擇某段時間之內使用頻次最小的鍵值對清除掉;
- volatile-ttl:從設定了過期時間的鍵中選擇過期時間最早的鍵值對清除;
- volatile-random:從設定了過期時間的鍵中,隨機選擇鍵進行清除;
- allkeys-lru:最近最少使用演算法,從所有的鍵中選擇空轉時間最長的鍵值對清除;
- allkeys-lfu:最近最不經常使用演算法,從所有的鍵中選擇某段時間之內使用頻次最少的鍵值對清除;
- allkeys-random:所有的鍵中,隨機選擇鍵進行刪除;
- noeviction:不做任何的清理工作,在redis的記憶體超過限制之後,所有的寫入操作都會返回錯誤;但是讀操作都能正常的進行。
maxclicents :設定同一時間客戶端最大連線數量,設定為0表示不作限制。
RDB(快照)
簡介
在指定的時間間隔內將記憶體中的資料集快照寫入磁碟,也就是行話講的Snapshot快照,它恢復時是將快照檔案直接讀到記憶體裡,Redis會單獨建立(fork)一個子程序來進行持久化,會先將資料寫入到一個臨時檔案中,待持久化過程都結束了,再用這個臨時檔案替換上次持久化好的檔案。整個過程中,主程序是不進行任何IO操作的,這就確保了極高的效能。如果需要進行大規模資料的恢復,且對於資料恢復的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。RDB的缺點是最後一次持久化後的資料可能丟失。
- 命令save或者是bgsave
SAVE:save時只管儲存,其它不管,全部阻塞
BGSAVE:Redis會在後臺非同步進行快照操作,快照同時還可以響應客戶端請求。可以通過lastsave
命令獲取最後一次成功執行快照的時間
注:執行flushall命令,也會產生dump.rdb檔案,但裡面是空的,無意義
save 900 1 //15分鐘內修改一次資料
save 300 10 //5分鐘內修改10次資料
save 60 10000 //1分鐘內修改10000次資料
save這一項後面需要加上兩個數字,分別代表秒數和更改數。假如設定了save m n,就代表如果在經過m秒之後發生了至少n次更改,Redis就會自動執行一次BGSAVE命令。save配置項可以同時存在多個,如果save太過頻繁,會影響到Redis的效能,頻率太低則會增加資料丟失的風險,所以建議根據需要對save項進行配置。如果移除所有的save配置項或者加上一項save “”,則自動儲存功能會被關閉。
stop-writes-on-bgsave-error yes
預設情況下,如果後臺儲存出錯了,Redis會停止接受寫操作。如果後臺的儲存程序重新開始工作,Redis也會自動恢復接受寫操作。這是一種比較簡單粗暴的解決方式,通過這種方式可以顯示地提醒維護者Redis出現了故障,但也會導致在故障被修復前Redis都沒辦法提供完整的服務。如果設定了stop-writes-on-bgsave-error為no,則Redis出問題的時候也可以照常工作,不過這就需要更細緻地監控Redis伺服器的變化。
rdbcompression yes
rdbcompression配置項設定是否對RDB檔案進行壓縮。如果將rdbcompression設定為no的話RDB檔案儲存的速度會快一些,但是儲存下來的檔案也會相應地變大,Redis使用LZF演算法壓縮RDB檔案,但會消耗CPU效能,
rdbchecksum yes
rdbchecksum配置項控制Redis是否使用迴圈冗餘檢驗。如果啟用迴圈冗餘檢驗,可以保證檔案的完整性,但是進行檔案儲存和載入時會損失10%左右的效能,如果追求最大效能可以考慮把這一項關閉。Redis使用的是CRC64。
dbfilename dump.rdb //配置RDB檔案的名字。
dir ./ //dir配置RDB檔案儲存的路徑。AOF產生的檔案也會被儲存到這個路徑下面。
優勢:
- 適合大規模的資料恢復,對資料完整性和一致性要求不高。
- 是對具體工程的全部造價進行估算,以滿足專案建議書、可行性研究和方案設計的需要。
- 使用單獨子程序來進行持久化,主程序不會進行任何IO操作,保證了redis的高效能。
劣勢:
- 有可能會造成資料丟失,fork的時候,記憶體中的資料被克隆一份,大致兩倍的膨脹性要考慮一下。
- RDB是間隔一段時間進行持久化,如果持久化之間redis發生故障,會發生資料丟失。所以這種方式更適合資料要求不嚴謹的時候。
總結
- RDB是一個非常緊湊的檔案
- RDB在儲存RDB檔案時父程序唯一需要做的就是folk出一個子程序,接下來工作全部交給子程序來做,父程序不需要再做其他IO操作,所以RDB持久化方式可以最大化redis的效能
- 與AOF相比,在恢復大的資料時候,RDB方式更快一些
- 資料丟失風險大
- RDB需要經常fork子程序來儲存資料集到磁碟,當資料集比較大額時候,fork的過程是比較耗時的,可能會導致redis在一些毫秒級不能響應客服端請求
AOF
簡介
Append-only file,將“操作 + 資料”以格式化指令的方式追加到操作日誌檔案的尾部,在append操作返回後(已經寫入到檔案或者即將寫入),才進行實際的資料變更,“日誌檔案”儲存了歷史所有的操作過程;當server需要資料恢復時,可以直接replay此日誌檔案,即可還原所有的操作過程。AOF相對可靠,它和mysql中bin.log、apache.log、zookeeper中txn-log簡直異曲同工。AOF檔案內容是字串,非常容易閱讀和解析。只要我們儲存了所有可能修改 Redis 記憶體資料的命令(也就是寫命令),那麼根據這些儲存的寫命令,我們可以重新恢復 Redis 的記憶體狀態。AOF 持久化正是利用這個原理來實現資料的持久化與資料的恢復的,Redis預設並沒有開啟aof快取。
特性:
AOF的特性決定了它相對比較安全,如果你期望資料更少的丟失,那麼可以採用AOF模式。如果AOF檔案正在被寫入時突然server失效,有可能導致檔案的最後一次記錄是不完整,你可以通過手工或者程式的方式去檢測並修正不完整的記錄,以便通過aof檔案恢復能夠正常;同時需要提醒,如果你的redis持久化手段中有aof,那麼在server故障失效後再次啟動前,需要檢測aof檔案的完整性。
- always:每一條aof記錄都立即同步到檔案,這是最安全的方式,也以為更多的磁碟操作和阻塞延遲,是IO開支較大。
- everysec:每秒同步一次,效能和安全都比較中庸的方式,也是redis推薦的方式。如果遇到物理伺服器故障,有可能導致最近一秒內aof記錄丟失(可能為部分丟失)。
- no:redis並不直接呼叫檔案同步,而是交給作業系統來處理,作業系統可以根據buffer填充情況/通道空閒時間等擇機觸發同步;這是一種普通的檔案操作方式。效能較好,在物理伺服器故障時,資料丟失量會因OS配置有關。
因為AOF採用檔案追加的方式持久化資料,所以檔案會越來越大,為了避免這種情況發生,增加了重寫機制。當AOF檔案的大小超過了配置所設定的闕值時,Redis就會啟動AOF檔案壓縮,只保留可以恢復資料的最小指令集,可以使用命令bgrewriteaof,闕值可以按需要配置,生產時一般3G。
AOF重寫機制:
aof 的方式也同時帶來了另一個問題。持久化檔案會變的越來越大。例如我們呼叫incr test命令100次,檔案中必須儲存全部的100條命令,其實有99條都是多餘的。因為要恢復資料庫的狀態其實檔案中儲存一條set test 100就夠了。為了壓縮aof的持久化檔案。redis提供了bgrewriteaof命令。收到此命令redis將使用與快照類似的方式將記憶體中的資料 以命令的方式儲存到臨時檔案中,最後替換原來的檔案。具體過程如下:
- redis呼叫fork ,現在有父子兩個程序
- 子程序根據記憶體中的資料庫快照,往臨時檔案中寫入重建資料庫狀態的命令
- 父程序繼續處理client請求,除了把寫命令寫入到原來的aof檔案中。同時把收到的寫命令快取起來。這樣就能保證如果子程序重寫失敗的話並不會出問題。
- 當子程序把快照內容寫入已命令方式寫到臨時檔案中後,子程序發訊號通知父程序。然後父程序把快取的寫命令也寫入到臨時檔案。
- 現在父程序可以使用臨時檔案替換老的aof檔案,並重命名,後面收到的寫命令也開始往新的aof檔案中追加。
需要注意到是重寫aof檔案的操作,並沒有讀取舊的aof檔案,而是將整個記憶體中的資料庫內容用命令的方式重寫了一個新的aof檔案,這點和快照有點類似。
優點:
- 資料完整性高。AOF 持久化的方法提供了多種的同步頻率,即使使用預設的同步頻率每秒同步一次,Redis 最多也就丟失 1 秒的資料而已。
- AOF 檔案使用 Redis 命令追加的形式來構造,因此,即使 Redis 只能向 AOF 檔案寫入命令的片斷,使用 redis-check-aof --fix appendonly.aof工具也很容易修正 AOF 檔案。
- AOF 檔案的格式可讀性較強,這也為使用者提供了更靈活的處理方式。例如,如果我們不小心錯用了 FLUSHALL 命令,在重寫還沒進行時,我們可以手工將最後的 FLUSHALL 命令去掉,然後再使用 AOF 來恢復資料。
缺點:
- AOF檔案比RDB檔案大,且恢復速度慢。
如果aof檔案異常無法恢復資料,可以用redis-check-aof --fix appendonly.aof來修復aof檔案
總結
因為rewrite操作/aof記錄同步/snapshot都消耗磁碟IO,redis採取了“schedule”策略:無論是“人工干預”還是系統觸發,snapshot和rewrite需要逐個被執行。
AOF rewrite過程並不阻塞客戶端請求。系統會開啟一個子程序來完成。
兩者都開啟的建議:RDB資料不實時,同時使用兩者時伺服器只會找AOF檔案,可不可以只使用AOF?建議不要,因為RDB更適合備份資料庫(AOF在不斷變化,不好備份),快速重啟,而且不會又AOF可能潛在的BUG,留作萬一的手段。