持久化就是將數據從掉電易失的內存同步到可以永久存儲的設備上的過程
redis將數據保存在內存中,一旦Redis服務器被關閉,或者運行Redis服務的主機自己被關閉的話,儲存在內存裏面的數據就會丟失php
若是僅僅將redis用做緩存的話,那麼這種數據丟失帶來的問題並非很是大,只須要重啓機器,而後再次將數據同步到緩存中就能夠了python
但若是將redis用做數據庫的話,那麼由於一些緣由致使數據丟失的狀況就不能接受mysql
Redis的持久化就是將儲存在內存裏面的數據以文件形式保存硬盤裏面,這樣即便Redis服務端被關閉,已經同步到硬盤裏面的數據也不會丟失linux
除此以外,持久化也可使Redis服務器重啓時,經過載入同步的持久文件來還原以前的數據,或者使用持久化文件來進行數據備份和數據遷移等工做ios
RDB持久化功能能夠將Redis中全部數據生成快照並以二進行文件的形式保存到硬盤裏,文件名爲.RDB文件redis
在Redis啓動時載入RDB文件,Redis讀取RDB文件內容,還原服務器原有的數據庫數據sql
過程以下圖所示:數據庫
Redis服務端建立RDB文件,有三種方式緩存
客戶端向Redis服務端發送SAVE命令,服務端把當前全部的數據同步保存爲一個RDB文件安全
經過向服務器發送SAVE命令,Redis會建立一個新的RDB文件
在執行SAVE命令的過程當中(也就是即時建立RDB文件的過程當中),Redis服務端將被阻塞,沒法處理客戶端發送的其餘命令請求
只有在SAVE命令執行完畢以後(也就時RDB文件建立完成以後),服務器纔會從新開始處理客戶端發送的命令請求
若是已經存在RDB文件,那麼服務器將自動使用新的RDB文件去代替舊的RDB文件
例子:
1.修改Redis的配置文件/etc/redis.conf
,把下面三行註釋掉
#save 900 1 #save 300 10 #save 60 10000
2.執行下面三條命令
127.0.0.1:6379> flushall # 清空Redis中全部的鍵值對 OK 127.0.0.1:6379> dbsize # 查看Redis中鍵值對數量 (integer) 0 127.0.0.1:6379> info memory # 查看Redis佔用的內存數爲834.26K # Memory used_memory:854280 used_memory_human:834.26K used_memory_rss:5931008 used_memory_rss_human:5.66M used_memory_peak:854280 used_memory_peak_human:834.26K total_system_memory:2080903168 total_system_memory_human:1.94G used_memory_lua:37888 used_memory_lua_human:37.00K maxmemory:0 maxmemory_human:0B maxmemory_policy:noeviction mem_fragmentation_ratio:6.94 mem_allocator:jemalloc-3.6.0
3.從Redis的配置文件能夠知道,Redis的RDB文件保存在/var/lib/redis/目錄中
[root@mysql redis]# pwd /var/lib/redis [root@mysql redis]# ll # 查看Redis的RDB目錄下的文件 total 0
4.執行python腳本,向Redis中插入500萬條數據
import redis client = redis.StrictRedis(host='192.168.81.101',port=6379) for i in range(5000000): client.sadd('key' + str(i),'value'+ str(i))
5.向Redis中寫入500萬條數據完成後,執行SAVE命令
127.0.0.1:6379> save # 執行SAVE命令,花費5.72秒 OK (5.72s)
6.切換另外一個Redis-cli窗口執行命令
127.0.0.1:6379> spop key1 # 執行spop命令彈出'key1'的值,由於SAVE命令在執行的緣由,spop命令會阻塞直到save命令執行完成,執行spop命令共花費4.36秒 "value1" (4.36s)
7.查看Redis佔用的內存數
127.0.0.1:6379> info memory # 向Redis中寫入500萬條數據後,Redis佔用1.26G內存容量 # Memory used_memory:1347976664 used_memory_human:1.26G used_memory_rss:1381294080 used_memory_rss_human:1.29G used_memory_peak:1347976664 used_memory_peak_human:1.26G total_system_memory:2080903168 total_system_memory_human:1.94G used_memory_lua:37888 used_memory_lua_human:37.00K maxmemory:0 maxmemory_human:0B maxmemory_policy:noeviction mem_fragmentation_ratio:1.02 mem_allocator:jemalloc-3.6.0 127.0.0.1:6379> dbsize # 查看Redis中數據總數 (integer) 4999999
8.在系統命令提示符中查看生成的RDB文件
[root@mysql redis]# ls -lah # Redis的RDB文件通過壓縮後的大小爲122MB total 122M drwxr-x--- 2 redis redis 22 Oct 13 15:31 . drwxr-xr-x. 64 root root 4.0K Oct 13 13:38 .. -rw-r--r-- 1 redis redis 122M Oct 13 15:31 dump.rdb
SAVE命令的時間複雜度爲O(N)
執行BGSAVE命令也會建立一個新的RDB文件
BGSAVE不會形成redis服務器阻塞:在執行BGSAVE命令的過程當中,Redis服務端仍然能夠正常的處理其餘的命令請求
BGSAVE命令執行步驟:
1.Redis服務端接受到BGSAVE命令 2.Redis服務端經過fork()來生成一個名叫redis-rdb-bgsave的進程,由redis-rdb-bgsave子進程來建立RDB文件,而Redis主進程則繼續處理客戶端的命令請求 3.當redis-rdb-bgsave子進程建立完成RDB文件,會向Redis主進程發送一個信號,告知Redis主進程RDB文件已經建立完畢,而後redis-rdb-bgsave子進程退出 4.Redis服務器(父進程)接手子進程建立的RDB文件,BGSAVE命令執行完畢
BGSAVE命令執行過程以下圖所示
Redis主進程由於建立子進程,會消耗額外的內存
須要注意的是:若是在Redis主進程fork子進程的過程當中花費的時間過多,Redis仍然可能會阻塞
BGSAVE是一個異步命令,Redis客戶端向Redis服務端發送BGSAVE命令後會當即獲得回覆,而實際的操做在Redis服務端回覆以後纔開始
例子:
如今Redis中已經有500萬條數據
1.刪除Redis的RDB文件
[root@mysql redis]# rm -rf *.rdb # 刪除Redis的舊的RDB文件 [root@mysql redis]# ll total 0
2.在redis-cli中執行BGSAVE命令
127.0.0.1:6379> bgsave # 執行BGSAVE命令後會當即獲得響應 Background saving started
3.在另外一個redis-cli中執行命令
127.0.0.1:6379> spop key2 # 從Redis的集合中彈出'key2'的值 "value2" 127.0.0.1:6379> dbsize # 查看Redis中全部數據的總數 (integer) 4999998 127.0.0.1:6379> info memory # 查看Redis佔用的內存數 # Memory used_memory:1347973736 used_memory_human:1.26G # Redis佔用了1.2G內存 used_memory_rss:1383464960 used_memory_rss_human:1.29G used_memory_peak:1348224368 used_memory_peak_human:1.26G total_system_memory:2080903168 total_system_memory_human:1.94G used_memory_lua:37888 used_memory_lua_human:37.00K maxmemory:0 maxmemory_human:0B maxmemory_policy:noeviction mem_fragmentation_ratio:1.03 mem_allocator:jemalloc-3.6.0
4.在系統命令提示符中執行命令
[root@mysql redis]# ps aux | grep redis | grep -v 'redis-cli' redis 856 3.1 66.3 1486404 1348920 ? Ssl 13:38 3:39 /usr/bin/redis-server 0.0.0.0:6379 # Redis的主進程 root 3015 0.0 0.0 112664 968 pts/3 R+ 15:36 0:00 grep --color=auto redis [root@mysql redis]# ps aux | grep redis | grep -v 'redis-cli' redis 856 3.0 66.3 1486404 1348956 ? Ssl 13:38 3:39 /usr/bin/redis-server 0.0.0.0:6379 # Redis的主進程 redis 3026 87.1 66.3 1486408 1348032 ? R 15:36 0:05 redis-rdb-bgsave 0.0.0.0:6379 # Redis主進程fork的子進程 root 3028 0.0 0.0 112664 968 pts/3 R+ 15:37 0:00 grep --color=auto redis [root@mysql redis]# pwd /var/lib/redis [root@mysql redis]# ls -lah # 查看BGSAVE命令運行後獲得的RDB文件 total 122M drwxr-x--- 2 redis redis 22 Oct 13 15:37 . drwxr-xr-x. 64 root root 4.0K Oct 13 13:38 .. -rw-r--r-- 1 redis redis 122M Oct 13 15:37 dump.rdb
BGSAVE命令的時間複雜度爲O(N)
SAVE命令與BGSAVE命令的區別
RDB持久化方式的總結
SAVE建立RDB文件的速度會比BGSAVE快,SAVE能夠集中資源來建立RDB文件 若是數據庫正在上線當中,就要使用BGSAVE 若是數據庫須要維護,可使用SAVE命令
打開Redis的配置文件/etc/redis.conf
save 900 1 save 300 10 save 60 10000
自動持久化配置解釋:
save 900 1表示:若是距離上一次建立RDB文件已通過去的900秒時間內,Redis中的數據發生了1次改動,則自動執行BGSAVE命令 save 300 10表示:若是距離上一次建立RDB文件已通過去的300秒時間內,Redis中的數據發生了10次改動,則自動執行BGSAVE命令 save 60 10000表示:若是距離上一次建立RDB文件已通過去了60秒時間內,Redis中的數據發生了10000次改動,則自動執行BGSAVE命令
當三個條件中的任意一個條件被知足時,Redis就會自動執行BGSAVE命令
須要注意的是:每次執行BGSAVE命令建立RDB文件以後,服務器爲實現自動持久化而設置的時間計數器和次數計數器就會被清零,並從新開始計數,因此多個保存條件的效果是不會疊加
用戶也能夠經過設置多個SAVE選項來設置自動保存條件,
Redis關於自動持久化的配置
rdbcompression yes 建立RDB文件時,是否啓用壓縮 stop-writes-on-bgsave-error yes 執行BGSAVE命令時發生錯誤是否中止寫入 rdbchecksum yes 是否對生成RDB文件進行檢驗 dbfilename dump.rdb 持久化生成的備份文件的名字 dir /var/lib/redis/6379 RDB文件保存的目錄
例子:
1.修改Redis配置文件/etc/redis.conf
save 900 1 save 300 10 save 60 5
2.重啓Redis,刪除已經建立的RDB文件
[root@mysql redis]# systemctl restart redis [root@mysql redis]# rm -rf dump.rdb [root@mysql redis]# pwd /var/lib/redis [root@mysql redis]# ls [root@mysql redis]#
3.打開redis-cli,向Redis中設置5個value
127.0.0.1:6379> flushall # 清空Redis中已有的全部數據 OK 127.0.0.1:6379> set hello world OK 127.0.0.1:6379> set a b OK 127.0.0.1:6379> set c d OK 127.0.0.1:6379> set e f OK 127.0.0.1:6379> set g i OK
4.查看Redis的日誌記錄
[root@mysql ~]# tail /var/log/redis/redis.log # 查看Redis日誌的最後10行 3325:M 13 Oct 15:53:44.323 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128. 3325:M 13 Oct 15:53:44.323 # Server started, Redis version 3.2.10 3325:M 13 Oct 15:53:44.323 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect. 3325:M 13 Oct 15:53:44.323 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled. 3325:M 13 Oct 15:53:44.323 * The server is now ready to accept connections on port 6379 3325:M 13 Oct 15:55:17.431 * 5 changes in 60 seconds. Saving... 3325:M 13 Oct 15:55:17.432 * Background saving started by pid 3349 3349:C 13 Oct 15:55:17.434 * DB saved on disk 3349:C 13 Oct 15:55:17.435 * RDB: 2 MB of memory used by copy-on-write 3325:M 13 Oct 15:55:17.534 * Background saving terminated with success
5.查看Redis的持久化文件
[root@mysql redis]# pwd /var/lib/redis [root@mysql redis]# ls -lah total 8.0K drwxr-x--- 2 redis redis 22 Oct 13 15:55 . drwxr-xr-x. 64 root root 4.0K Oct 13 13:38 .. -rw-r--r-- 1 redis redis 115 Oct 13 15:55 dump.rdb
RDB現存問題
1.耗時耗性能
Redis把內存中的數據dump到硬盤中生成RDB文件,首先要把全部的數據都進行持久化,所須要的時間複雜度爲O(N),同時把數據dump到文件中,也須要消耗CPU資源,
因爲BGSAVE命令有一個fork子進程的過程,雖然不是完整的內存拷貝,而是基於copy-on-write的策略,可是若是Redis中的數據很是多,佔用的內存頁也會很是大,fork子進程時消耗的內存資源也會不少
磁盤IO性能的消耗,生成RDB文件原本就是把內存中的數據保存到硬盤當中,若是生成的RDB文件很是大,保存到硬盤的過程當中消耗很是多的硬盤IO
2.不可控,丟失數據
自動建立RDB文件的過程當中,在上一次建立RDB文件之後,又向Redis中寫入多條數據,若是此時Redis服務中止,則從上一次建立RDB文件到Redis服務掛機這個時間段內的數據就丟失了
AOF建立
當向Redis中寫入一條數據時,就向AOF文件中添加一條寫記錄
以下圖所示
AOF恢復
Redis發生宕機重啓後,讀取AOF文件對Redis中的數據進行完整的恢復,並且使用AOF文件來恢復Redis中的數據是實時的
以下圖所示
AOF持久化保存數據庫的方法是:每當有修改的數據庫的命令被執行時,服務器就會將執行的命令寫入到AOF文件的末尾。
由於AOF文件裏面儲存了服務器執行過的全部數據庫修改的命令,因此Redis只要從新執行一遍AOF文件裏面保存的命令,就能夠達到還原數據庫的目的
雖然服務器執行一次修改數據庫的命令,執行的命令就會被寫入到AOF文件,但這並不意味着AOF持久化方式不會丟失任何數據
在linux系統中,系統調用write函數,將一些數據保存到某文件時,爲了提升效率,系統一般不會直接將內容寫入硬盤裏面,而是先把數據保存到硬盤的緩衝區之中。
等到緩衝區被填滿,或者用戶執行fsync
調用和fdatasync
調用時,操做系統纔會將儲存在緩衝區裏的內容真正的寫入到硬盤裏
對於AOF持久化來講,當一條命令真正的被寫入到硬盤時,這條命令纔不會由於停機而意外丟失
所以,AOF持久化在遭遇停機時丟失命令的數量,取決於命令被寫入硬盤的時間
越早將命令寫入到硬盤,發生意外停機時丟失的數據就越少,而越遲將命令寫入硬盤,發生意外停機時丟失的數據就越多
爲了控制Redis服務器在遇到意外停機時丟失的數據量,Redis爲AOF持久化提供了appendfsync
選項,這個選項的值能夠是always,everysec或者no
Always
Redis每寫入一個命令,always會把每條命令都刷新到硬盤的緩衝區當中而後將緩衝區裏的數據寫入到硬盤裏。 這種模式下,Redis即便用遭遇意外停機,也不會丟失任何本身已經成功執行的數據
Everysec
Redis每一秒調用一次fdatasync,將緩衝區裏的命令寫入到硬盤裏, 這種模式下,當Redis的數據交換不少的時候能夠保護硬盤 即便Redis遭遇意外停機時,最多隻丟失一秒鐘內的執行的數據
No
服務器不主動調用fdatasync,由操做系統決定任何將緩衝區裏面的命令寫入到硬盤裏,這種模式下,服務器遭遇意外停機時,丟失的命令的數量是不肯定的
運行速度:always的速度慢,everysec和no都很快 always不丟失數據,可是硬盤IO開銷不少,通常的SATA硬盤一秒種只能寫入幾百次數據 everysec每秒同步一次數據,若是Redis發生故障,可能會丟失1秒鐘的數據 no則系統控制,不可控,不知道會丟失多少數據
隨着服務器的不斷運行,爲了記錄Redis中數據的變化,Redis會將愈來愈多的命令寫入到AOF文件中,使得AOF文件的體積來斷增大
爲了讓AOF文件的大小控制在合理的範圍,redis提供了AOF重寫功能,經過這個功能,服務器能夠產生一個新的AOF文件:
新的AOF文件記錄的數據庫數據和原有AOF文件記錄的數據庫數據徹底同樣 新的AOF文件會使用盡量少的命令來記錄數據庫數據,所以新的AOF文件的體積一般會比原有AOF文件的體積要小得多 AOF重寫期間,服務器不會被阻塞,能夠正常處理客戶端發送的命令請求
AOF重寫功能就是把Redis中過時的,再也不使用的,重複的以及一些能夠優化的命令進行優化,從新生成一個新的AOF文件,從而達到減小硬盤佔用量和加速Redis恢復速度的目的
1.向Redis發送BGREWRITEAOF
命令
相似於BGSAVE命令,Redis主進程會fork一個子進程,由子進程去完成AOF重寫
這裏的AOF重寫是將Redis內存中的數據進行一次回溯,獲得一個AOF文件,而不是將已有的AOF文件重寫成一個新的AOF文件
2.經過配置選項自動執行BGREWRITEAOF命令
auto-aof-rewrite-min-size
觸發AOF重寫所需的最小體積:只要在AOF文件的大小超過設定的size時,Redis會進行AOF重寫,這個選項用於避免對體積太小的AOF文件進行重寫
auto-aof-rewrite-percentage
指定觸發重寫所需的AOF文件體積百分比:當AOF文件的體積大於auto-aof-rewrite-min-size指定的體積,而且超過上一次重寫以後的AOF文件體積的percent%時,就會觸發AOF重寫,若是服務器剛啓動不久,尚未進行過AOF重寫,那麼使用服務器啓動時載入的AOF文件的體積來做爲基準值。 將這個值設置爲0表示關閉自動AOF重寫功能
只有當上面兩個條件同時知足時纔會觸發Redis的AOF重寫功能
如上圖所示:
1.不管是執行bgrewriteaof命令仍是自動進行AOF重寫,實際上都是執行BGREWRITEAOF命令 2.執行bgrewriteaof命令,Redis會fork一個子進程, 3.子進程對內存中的Redis數據進行回溯,生成新的AOF文件 4.Redis主進程會處理正常的命令操做 5.同時Redis把會新的命令寫入到aof_rewrite_buf當中,當bgrewriteaof命令執行完成,新的AOF文件生成完畢,Redis主進程會把aof_rewrite_buf中的命令追加到新的AOF文件中 6.用新生成的AOF文件替換舊的AOF文件
appendonly no # 改成yes,開啓AOF功能 appendfilename "appendonly.aof" # 生成的AOF的文件名 appendfsync everysec # AOF同步的策略 no-appendfsync-on-rewrite no # AOF重寫時,是否作append的操做 AOF重寫很是消耗服務器的性能,子進程要將內存中的數據刷到硬盤中,確定會消耗硬盤的IO 而正常的AOF也要將內存中的數據寫入到硬盤當中,此時會有必定的衝突 由於rewrite的過程在數據量比較大的時候,會佔用大量的硬盤的IO 在AOF重寫後,生成的新的AOF文件是完整且安全的數據 若是AOF重寫失敗,若是設置爲no則正常的AOF文件中會丟失一部分數據 生產環境中會在yes和no之間進行必定的權衡,經過優先從性能方面進行考慮,設置爲yes auto-aof-rewrite-percentage 100 # 觸發重寫所需的AOF文件體積增加率 auto-aof-rewrite-min-size 64mb # 觸發重寫所需的AOF文件大小
1.打開一個Redis客戶端
[root@mysql ~]# redis-cli 127.0.0.1:6379> config get appendonly # 查看appendonly配置項結果 1) "appendonly" 2) "no" 127.0.0.1:6379> config set appendonly yes # 設置appendonly選項爲yes OK 127.0.0.1:6379> config rewrite # 把配置寫入到文件中 OK 127.0.0.1:6379> config get appendonly # 再次查看appendonly選項結果,看修改是否寫入到配置文件中 1) "appendonly" 2) "yes" 127.0.0.1:6379> set hello world OK 127.0.0.1:6379> set hello php OK 127.0.0.1:6379> set hello python OK 127.0.0.1:6379> incr counter (integer) 1 127.0.0.1:6379> incr counter (integer) 2 127.0.0.1:6379> rpush list a (integer) 1 127.0.0.1:6379> rpush list b (integer) 2 127.0.0.1:6379> rpush list c (integer) 3 127.0.0.1:6379> dbsize # 查看Redis中數據量 (integer) 3
2.在系統命令提示符中查看AOF文件的大小
[root@mysql redis]# ll -h # 正常的AOF文件大小爲278B total 8.0K -rw-r--r-- 1 redis redis 278 Oct 13 18:32 appendonly.aof -rw-r--r-- 1 redis redis 135 Oct 13 18:32 dump.rdb
3.在Redis客戶端執行AOF重寫命令
127.0.0.1:6379> bgrewriteaof # 在Redis客戶端中執行AOF重寫命令 Background append only file rewriting started
4.再次在系統命令提示符中查看新的AOF文件大小
[root@mysql redis]# ll -h total 8.0K -rw-r--r-- 1 redis redis 138 Oct 13 18:33 appendonly.aof # AOF重寫後文件大小爲138B -rw-r--r-- 1 redis redis 135 Oct 13 18:32 dump.rdb [root@mysql redis]#
Redis的單機多部署模式對服務器的CPU,內存,硬盤有較大開銷,實際生產環境根據須要進行設定
通常分配服務器60%到70%的內存給Redis使用,剩餘的內存分留給相似fork的操做
max_memory
對Redis進行規劃,例如Redis使用單機多部署模式時,每一個Redis可用內存設置爲4G,這樣不管是使用RDB模式仍是AOF模式進行持久化,fork子進程操做都只須要較小的開銷不要佔用100%的內存
上面的策略,不管使用RDB仍是使用AOF,均可以作爲參考
fork與內存量息息相關:Redis中數據佔用的內存越大,耗時越長(與機器類型有關),能夠經過info memory命令查看上次fork操做消耗的微秒數:latest_fork_usec:0
fork操做優化:
1.優先使用物理機或者高效支持fork操做的虛擬化技術 2.控制Redis實例最大可用內存:maxmemory 3.合理配置linux內存分配策略:vm.overcommit_memory = 1 4.下降fork頻率,例如放寬AOF重寫自動觸發機制,沒必要要的全量複製
RDB和AOF文件的生成操做都屬於CPU密集型
一般子進程的開銷會佔用90%以上的CPU,文件寫入是很是密集的過程
CPU開銷優化
3.在使用單機部署Redis時,不要發生大量的RDB,BGSAVE,AOF的過程,保證能夠節省必定的CPU資源
fork子進程會產生必定內存開銷,理論上fork子進程操做佔用的內存是等於父進程佔用的內存
在linux系統中,有一種顯式複製的機制:copy-on-write,父子進程會共享相同的物理內存頁,當父進程有寫請求的時候,會建立一個父本,此時纔會消耗必定的內存。在這個過程當中,子進程會共享fork時,父進程的內存的快照
Redis在作BGSAVE或者AOF操做fork產生子進程的過程當中,若是父進程的內存頁有大量的寫入操做時子進程的內存開銷會很是大,由於子進程會作一個父本
若是父進程沒有多少寫入操做時,fork操做不會佔用過多的內存資源,能夠在Redis的日誌中看到
內存開銷優化:
3.linux系統優化:
echo never > /sys/kernel/mm/transparent_hugepage/enabled
AOF和RDB文件的寫入,會佔用硬盤的IO及容量,可使用iostat
命令和iotop
命令查看分析
硬盤開銷優化:
2.修改Redis配置文件:在AOF重寫期間不要執行AOF操做,以減小內存開銷
no-appendfsync-on-rewrite = yes
4.單機多部署模式持久化時,文件目錄能夠考慮分盤。即對不一樣的Redis實例以端口來進行區分,持久化文件也以端口來區分
AOF通常都是一秒中執行一次
AOF追加阻塞流程
1.主線程負責寫入AOF緩衝區 2.AOF同步線程每秒鐘執行一次同步硬盤操做,同時還會記錄一次最近一次的同步時間 3.主線程會對比上次AOF同步時間,若是距離上次同步時間在2秒以內,則返回主線程 4.若是距離上次AOF同步時間超過2秒,則主線程會阻塞,直到同步完成
AOF追加阻塞是保證AOF文件安全性的一種策略
爲了達到每秒刷盤的效果,主線程會阻塞直到同步完成
這樣就會產生兩個問題:
由於主線程是在負責Redis平常命令的處理,因此Redis主線程不能阻塞,而此時Redis的主線程被阻塞
若是AOF追加被阻塞,每秒刷盤的策略並不會每秒都執行,可能會丟失2秒的數據
AOF阻塞定位:
若是AOF追加被阻塞,能夠經過命令查看:
127.0.0.1:6379> info persistence # Persistence loading:0 rdb_changes_since_last_save:1 rdb_bgsave_in_progress:0 rdb_last_save_time:1539409132 rdb_last_bgsave_status:ok rdb_last_bgsave_time_sec:-1 rdb_current_bgsave_time_sec:-1 aof_enabled:0 aof_rewrite_in_progress:0 aof_rewrite_scheduled:0 aof_last_rewrite_time_sec:-1 aof_current_rewrite_time_sec:-1 aof_last_bgrewrite_status:ok aof_last_write_status:ok aof_delayed_fsync:100 # AOF被阻塞的歷史次數,沒法看到某次AOF被阻塞的時間點
單機多實例部署中持久化的優化能夠參考硬盤開銷的優化策略
RDB是Redis內存數據到硬盤的快照,用於持久化 save一般會阻塞Redis BGSAVE不會阻塞Redis,可是fork新進程會阻塞Redis SAVE自動配置知足任一條件就會被執行