緣起:
今天早晨收到報警,服務不干活了,趕緊起來看問題。。。
為了盡快讓服務可用,嘗試重啟服務,發現服務起不來,報錯
redis connection failed!
看起來是redis掛了,但是發現redis的進程還在。進一步看服務的錯誤日志:
redis.clients.jedis.exceptions.JedisDataException: MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the d
ata set are disabled. Please check Redis logs for details about the error.
redis持久化失敗,服務配置了redis rdb持久化方式,為啥失敗呢?內存和硬盤看了下,果然硬盤滿了。清理硬盤ok了。
redis持久化策略(RDB/AOF)
1、RDB快照(snapshots)
缺省情況情況下,Redis把數據快照存放在磁盤上的二進制文件中,文件名為dump.rdb。你可以配置Redis的持久化策略,例如數據集中每N秒鍾有超過M次更新,就將數據寫入磁盤;或者你可以手工調用命令SAVE或BGSAVE。
數據保存的目錄:
工作原理
- Redis forks.
- 子進程開始將數據寫到臨時RDB文件中。
- 當子進程完成寫RDB文件,用新文件替換老文件。
- 這種方式可以使Redis使用copy-on-write技術。
寫時復制(copy-on-write/COW)技術:
寫入時復制(Copy-on-write)是一個被使用在程式設計領域的最佳化策略。其基礎的觀念是,如果有多個呼叫者(callers)同時要求相同資源,他們會共同取得相同的指標指向相同的資源,直到某個呼叫者(caller)嘗試修改資源時,系統才會真正復制一個副本(private copy)給該呼叫者,以避免被修改的資源被直接察覺到,這過程對其他的呼叫只都是通透的(transparently)。此作法主要的優點是如果呼叫者並沒有修改該資源,就不會有副本(private copy)被建立。
2、APPEND ONLY MODE(AOF)
快照模式並不十分健壯,當系統停止,或者無意中Redis被kill掉,最后寫入Redis的數據就會丟失。這對某些應用也許不是大問題,但對於要求高可靠性的應用來說,Redis就不是一個合適的選擇。
Append-only文件模式是另一種選擇。
你可以在配置文件中打開AOF模式:
選項:
1、appendfsync no
當設置appendfsync為no的時候,Redis不會主動調用fsync去將AOF日志內容同步到磁盤,所以這一切就完全依賴於操作系統的調試了。對大多數Linux操作系統,是每30秒進行一次fsync,將緩沖區中的數據寫到磁盤上。
2、appendfsync everysec
當設置appendfsync為everysec的時候,Redis會默認每隔一秒進行一次fsync調用,將緩沖區中的數據寫到磁盤。但是當這一 次的fsync調用時長超過1秒時。Redis會采取延遲fsync的策略,再等一秒鍾。也就是在兩秒后再進行fsync,這一次的fsync就不管會執行多長時間都會進行。這時候由於在fsync時文件描述符會被阻塞,所以當前的寫操作就會阻塞。
所以,結論就是:在絕大多數情況下,Redis會每隔一秒進行一次fsync。在最壞的情況下,兩秒鍾會進行一次fsync操作。
這一操作在大多數數據庫系統中被稱為group commit,就是組合多次寫操作的數據,一次性將日志寫到磁盤。
3、appednfsync always
當設置appendfsync為always時,每一次寫操作都會調用一次fsync,這時數據是最安全的,當然,由於每次都會執行fsync,所以其性能也會受到影響
建議采用 appendfsync everysec(缺省方式)
快照模式可以和AOF模式同時開啟,互補影響
3、AOF重寫
AOF文件是可識別的純文本,它的內容就是一個個的Redis標准命令,
AOF日志也不是完全按客戶端的請求來生成日志的,比如命令 INCRBYFLOAT 在記AOF日志時就被記成一條SET記錄,因為浮點數操作可能在不同的系統上會不同,所以為了避免同一份日志在不同的系統上生成不同的數據集,所以這里只將操作后的結果通過SET來記錄。
每一條寫命令都生成一條日志,AOF文件會很大。
AOF重寫是重新生成一份AOF文件,新的AOF文件中一條記錄的操作只會有一次,而不像一份老文件那樣,可能記錄了對同一個值的多次操作。其生成過程和RDB類似,也是fork一個進程,直接遍歷數據,寫入新的AOF臨時文件。在寫入新文件的過程中,所有的寫操作日志還是會寫到原來老的 AOF文件中,同時還會記錄在內存緩沖區中。當重完操作完成后,會將所有緩沖區中的日志一次性寫入到臨時文件中。然后調用原子性的rename命令用新的 AOF文件取代老的AOF文件
命令:BGREWRITEAOF, 我們應該經常調用這個命令來來重寫
數據恢復:
- 如果只配置AOF,重啟時加載AOF文件恢復數據;
- 如果同時 配置了RBD和AOF,啟動是只加載AOF文件恢復數據;
- 如果只配置RBD,啟動是講加載dump文件恢復數據。
寫數據的流程:
- 客戶端向服務端發送寫操作(數據在客戶端的內存中)。
- 數據庫服務端接收到寫請求的數據(數據在服務端的內存中)。
- 服務端調用write這個系統調用,將數據往磁盤上寫(數據在系統內存的緩沖區中)。
- 操作系統將緩沖區中的數據轉移到磁盤控制器上(數據在磁盤緩存中)。
- 磁盤控制器將數據寫到磁盤的物理介質中(數據真正落到磁盤上)。