記錄一次因為硬盤寫滿造成的redis無法連接


緣起:

今天早晨收到報警,服務不干活了,趕緊起來看問題。。。

為了盡快讓服務可用,嘗試重啟服務,發現服務起不來,報錯

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次更新,就將數據寫入磁盤;或者你可以手工調用命令SAVEBGSAVE

數據保存的目錄:

 

工作原理

  • 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文件恢復數據。

 

寫數據的流程:

    1. 客戶端向服務端發送寫操作(數據在客戶端的內存中)。
    2. 數據庫服務端接收到寫請求的數據(數據在服務端的內存中)。
    3. 服務端調用write這個系統調用,將數據往磁盤上寫(數據在系統內存的緩沖區中)。
    4. 操作系統將緩沖區中的數據轉移到磁盤控制器上(數據在磁盤緩存中)。
    5. 磁盤控制器將數據寫到磁盤的物理介質中(數據真正落到磁盤上)。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM