1. 程式人生 > >Redis持久化磁盤IO方式及其帶來的問題   有Redis線上運維經驗的人會發現Redis在物理內存使用比較多,但還沒有超過實際物理內存總容量時就會發生不穩定甚至崩潰的問題,有人認為是基於快照方式持

Redis持久化磁盤IO方式及其帶來的問題   有Redis線上運維經驗的人會發現Redis在物理內存使用比較多,但還沒有超過實際物理內存總容量時就會發生不穩定甚至崩潰的問題,有人認為是基於快照方式持

發出 != hot server 磁盤io loaddata set 自動 選擇

轉自:http://blog.csdn.net/kaosini/article/details/9176961

一、對Redis持久化的探討與理解

redis是一個支持持久化的內存數據庫,也就是說redis需要經常將內存中的數據同步到磁盤來保證持久化。redis支持兩種持久化方式,一種是 Snapshot(RDB)也是默認方式,另一種是Append only file(AOF)的方式。具體的理論說明請見這裏。

我們應該明確持久化的數據有什麽用,答案是用於重啟後的數據恢復。Redis是一個內存數據庫,無論是RDB還是AOF,都只是其保證數據恢復的措施。所以Redis在利用RDB和AOF進行恢復的時候,都會讀取RDB或AOF文件,重新加載到內存中。

RDB就是Snapshot快照存儲,是默認的持久化方式。即按照一定的策略周期性的將數據保存到磁盤。對應產生的數據文件為dump.rdb,通過配置文件中的save參數來定義快照的周期。Redis支持將當前數據的快照存成一個數據文件的持久化機制。而一個持續寫入的數據庫如何生成快照呢。Redis借助了fork命令的copy on write機制。在生成快照時,將當前進程fork出一個子進程,然後在子進程中循環所有的數據,將數據寫成為RDB文件。

Redis的RDB文件不會壞掉,因為其寫操作是在一個新進程中進行的。當生成一個新的RDB文件時,Redis生成的子進程會先將數據寫到一個臨時文件中,然後通過原子性rename系統調用將臨時文件重命名為RDB文件。這樣在任何時候出現故障,Redis的RDB文件都總是可用的。並且Redis的RDB文件也是Redis主從同步內部實現中的一環:
第一次Slave向Master同步的實現是:
Slave向Master發出同步請求,Master先dump出rdb文件,然後將rdb文件全量傳輸給slave,然後Master把緩存的命令轉發給Slave,初次同步完成。
第二次以及以後的同步實現是:
Master將變量的快照直接實時依次發送給各個Slave。但不管什麽原因導致Slave和Master斷開重連都會重復以上兩個步驟的過程。
Redis的主從復制是建立在內存快照的持久化基礎上的,只要有Slave就一定會有內存快照發生。

不足:就是一旦數據庫出現問題,那麽我們的RDB文件中保存的數據並不是全新的,從上次RDB文件生成到Redis停機這段時間的數據全部丟掉了(因為刷寫機制還沒有出發)。RDB就是Snapshot快照存儲,是默認的持久化方式。相關參數:

 1 ################################ SNAPSHOTTING  #################################
 2 # Save the DB on disk:
 3 #  設置sedis進行數據庫鏡像的頻率。
 4 #  900秒(15分鐘)內至少1個key值改變(則進行數據庫保存--持久化)。
 5 #  300秒(5分鐘)內至少10個key值改變(則進行數據庫保存--持久化)。
 6 #  60秒(1分鐘)內至少10000個key值改變(則進行數據庫保存--持久化)。
 7 save 900 1
 8 save 300 10
 9 save 60 10000
10 
11 stop-writes-on-bgsave-error yes
12 # 在進行鏡像備份時,是否進行壓縮。yes:壓縮,但是需要一些cpu的消耗。no:不壓縮,需要更多的磁盤空間。
13 rdbcompression yes
14 # 一個CRC64的校驗就被放在了文件末尾,當存儲或者加載rbd文件的時候會有一個10%左右的性能下降,為了達到性能的最大化,你可以關掉這個配置項。
15 rdbchecksum yes
16 # 快照的文件名
17 dbfilename dump.rdb
18 # 存放快照的目錄
19 dir /var/lib/redis 

AOF(Append Only File)比RDB方式有更好的持久化性。由於在使用AOF持久化方式時,Redis會將每一個收到的寫命令都通過Write函數追加到文件中,類似於MySQL的binlog。當Redis重啟是會通過重新執行文件中保存的寫命令來在內存中重建整個數據庫的內容。

AOF的完全持久化方式同時也帶來了另一個問題,持久化文件會變得越來越大。(比如我們調用INCR test命令100次,文件中就必須保存全部的100條命令,但其實99條都是多余的。因為要恢復數據庫的狀態其實文件中保存一條SET test 100就夠了)。為了壓縮AOF的持久化文件,Redis提供了bgrewriteaof命令。收到此命令後Redis將使用與快照類似的方式將內存中的數據以命令的方式保存到臨時文件中,最後替換原來的文件,以此來實現控制AOF文件的增長。由於是模擬快照的過程,因此在重寫AOF文件時並沒有讀取舊的AOF文件,而是將整個內存中的數據庫內容用命令的方式重寫了一個新的AOF文件。相關參數:

 1 ############################## APPEND ONLY MODE ###############################
 2 # 是否開啟AOF,默認關閉(no)
 3 appendonly yes
 4 # 指定 AOF 文件名
 5 appendfilename appendonly.aof
 6 # Redis支持三種不同的刷寫模式:
 7 # appendfsync always #每次收到寫命令就立即強制寫入磁盤,是最有保證的完全的持久化,但速度也是最慢的,一般不推薦使用。
 8 appendfsync everysec #每秒鐘強制寫入磁盤一次,在性能和持久化方面做了很好的折中,是受推薦的方式。
 9 # appendfsync no     #完全依賴OS的寫入,一般為30秒左右一次,性能最好但是持久化最沒有保證,不被推薦。
10 
11 #在日誌重寫時,不進行命令追加操作,而只是將其放在緩沖區裏,避免與命令的追加造成DISK IO上的沖突。
12 #設置為yes表示rewrite期間對新寫操作不fsync,暫時存在內存中,等rewrite完成後再寫入,默認為no,建議yes
13 no-appendfsync-on-rewrite yes 
14 #當前AOF文件大小是上次日誌重寫得到AOF文件大小的二倍時,自動啟動新的日誌重寫過程。
15 auto-aof-rewrite-percentage 100
16 #當前AOF文件啟動新的日誌重寫過程的最小值,避免剛剛啟動Reids時由於文件尺寸較小導致頻繁的重寫。
17 auto-aof-rewrite-min-size 64mb

到底選擇什麽呢?下面是來自官方的建議:
通常,如果你要想提供很高的數據保障性,那麽建議你同時使用兩種持久化方式。如果你可以接受災難帶來的幾分鐘的數據丟失,那麽你可以僅使用RDB。
很多用戶僅使用了AOF,但是我們建議,既然RDB可以時不時的給數據做個完整的快照,並且提供更快的重啟,所以最好還是也使用RDB。
在數據恢復方面:
RDB的啟動時間會更短,原因有兩個:
一是RDB文件中每一條數據只有一條記錄,不會像AOF日誌那樣可能有一條數據的多次操作記錄。所以每條數據只需要寫一次就行了。
另一個原因是RDB文件的存儲格式和Redis數據在內存中的編碼格式是一致的,不需要再進行數據編碼工作,所以在CPU消耗上要遠小於AOF日誌的加載。

註意:

上面說了RDB快照的持久化,需要註意:在進行快照的時候(save),fork出來進行dump操作的子進程會占用與父進程一樣的內存,真正的copy-on-write,對性能的影響和內存的耗用都是比較大的。比如機器8G內存,Redis已經使用了6G內存,這時save的話會再生成6G,變成12G,大於系統的8G。這時候會發生交換;要是虛擬內存不夠則會崩潰,導致數據丟失。所以在用redis的時候一定對系統內存做好容量規劃。

目前,通常的設計思路是利用Replication機制來彌補aof、snapshot性能上的不足,達到了數據可持久化。即Master上Snapshot和AOF都不做,來保證Master的讀寫性能,而Slave上則同時開啟Snapshot和AOF來進行持久化,保證數據的安全性。

二、對Redis持久化的測試

通過上面的理論對snapshot和aof有了一定的理解,下面開始進行一些測試::
1、redis.conf 基本配置: 開啟snapshot,關閉aof

 1 save 900 1
 2 save 300 10
 3 save 60 10000
 4 
 5 rdbcompression no
 6 rdbchecksum no
 7 dbfilename zhoujy.rdb
 8 dir /var/lib/redis
 9 
10 appendonly  no

操作

 1 redis 127.0.0.1:6379> keys *                     #查看0庫下是否有key
 2 (empty list or set)
 3 redis 127.0.0.1:6379> set name zhoujinyi         #set操作
 4 OK
 5 redis 127.0.0.1:6379> set sex man
 6 OK
 7 redis 127.0.0.1:6379> set age 27
 8 OK
 9 redis 127.0.0.1:6379> keys *
10 1) "age"
11 2) "sex"
12 3) "name"
13 redis 127.0.0.1:6379> 
14 [email protected]:~$ ls -lh /var/lib/redis/          #rdb文件初始化大小
15 總用量 4.0K
16 -rw-rw---- 1 redis redis 18 2013-05-25 16:19 zhoujy.rdb
17 [email protected]:~$ redis
18 redis 127.0.0.1:6379> save                       #保存,進行持久化,每執行一次save,會在日至裏面記錄一條:“ * DB saved on disk ”
19 OK
20 redis 127.0.0.1:6379> 
21 [email protected]:~$ ls -lh /var/lib/redis/          #文件大小改變,數據寫入文件進行了持久化
22 總用量 4.0K
23 -rw-rw---- 1 redis redis 52 2013-05-25 16:20 zhoujy.rdb
24 
25 驗證持久化,重啟redis:
26 
27 redis 127.0.0.1:6379> keys *
28 1) "name"
29 2) "age"
30 3) "sex"
31 redis 127.0.0.1:6379> set address hangzhou        #key沒有被保存就重啟了
32 OK
33 redis 127.0.0.1:6379> 
34 [email protected]:~$ sudo /etc/init.d/redis-server restart
35 Stopping redis-server: redis-server.
36 Starting redis-server: redis-server.
37 [email protected]:~$ redis
38 redis 127.0.0.1:6379> keys *                      #發現剛才沒有被保存的key也被持久化了,怎麽回事?
39 1) "name"                                         
40 2) "address"
41 3) "sex"
42 4) "age"
43 redis 127.0.0.1:6379> 
44 
45 查看日誌,看看日誌裏面有什麽信息:
46 
47 [21154] 25 May 16:28:12.122 # User requested shutdown...
48 [21154] 25 May 16:28:12.122 * Saving the final RDB snapshot before exiting.
49 [21154] 25 May 16:28:12.165 * DB saved on disk
50 [21154] 25 May 16:28:12.165 * Removing the pid file.
51 [21154] 25 May 16:28:12.165 * Removing the unix socket file.
52 [21154] 25 May 16:28:12.165 # Redis is now ready to exit, bye bye...
53 
54 從日誌裏面得到了解釋,正常關閉redis,他會自己在關閉前執行save命令。那異常關閉呢? 用kill的效果和上面一樣,屬於正常關閉。只能用kill -9 才行:
54 55 redis 127.0.0.1:6379> keys * 56 1) "age" 57 2) "name" 58 3) "sex" 59 4) "address" 60 redis 127.0.0.1:6379> set company dxy 61 OK 62 redis 127.0.0.1:6379> keys * 63 1) "name" 64 2) "sex" 65 3) "age" 66 4) "address" 67 5) "company" 68 redis 127.0.0.1:6379> #key沒有被保存就重啟了 69 [email protected]:~$ sudo kill -9 21250 70 [email protected]:~$ redis 71 Could not connect to Redis at 127.0.0.1:6379: Connection refused 72 not connected> 73 [email protected]:~$ sudo /etc/init.d/redis-server start 74 Starting redis-server: redis-server. 75 [email protected]:~$ redis 76 redis 127.0.0.1:6379> keys * #company沒有被持久化,數據丟失,重啟日誌裏沒有“* DB saved on disk” 信息 77 1) "sex" 78 2) "age" 79 3) "address" 80 4) "name" 81 redis 127.0.0.1:6379>

從上面的結果看出,開啟RDB持久化,在滿足save條件、手動save、正常關閉的時候數據都會被持久化,而異常關閉終止的時候數據丟失。

2、redis.conf 基本配置: 關閉snapshot,關閉aof

1 #save 900 1
2 #save 300 10
3 #save 60 10000
4 rdbcompression no
5 rdbchecksum no
6 dbfilename zhoujy.rdb
7 dir /var/lib/redis
8 
9 appendonly  no

操作

 1 redis 127.0.0.1:6379> keys *                         #查看0庫下是否有key
 2 (empty list or set)
 3 redis 127.0.0.1:6379> set name zhoujinyi             #set操作
 4 OK
 5 redis 127.0.0.1:6379> set sex man
 6 OK
 7 redis 127.0.0.1:6379> set age 27
 8 OK
 9 redis 127.0.0.1:6379> save                           #保存,進行持久化,即使沒有開始snapshot,執行save命令一樣可以持久化,不手動的觸發永遠不會持久化。
10 OK                                                   #每執行一次save,會在日誌裏面記錄一條:“ * DB saved on disk ”
11 redis 127.0.0.1:6379> set address hangzhou           #set操作,但不save,正常重啟
12 OK
13 redis 127.0.0.1:6379> 
14 [email protected]:~$ sudo /etc/init.d/redis-server restart #正常重啟
15 [sudo] password for zhoujy: 
16 Stopping redis-server: redis-server.
17 Starting redis-server: redis-server.
18 [email protected]:~$ redis
19 redis 127.0.0.1:6379> keys *                          #發現剛才沒有被保存的key丟失了
20 1) "sex"
21 2) "name"
22 3) "age"
23 redis 127.0.0.1:6379> 

從上面的結果看出,關閉持久化,只有在手動save的時候數據都會被持久化,正常關閉的時候數據丟失。要是從一開始到關閉寫入的數據沒有手動save,則數據全部丟失!既然能手動save間接的說明了快照一直都存在,所以不能說是禁止snapshot,應該是禁止自動snapshot功能。

通過1,2驗證了之前說的:一旦數據庫出現問題,那麽我們的RDB文件中保存的數據並不是全新的。

3、redis.conf 基本配置: 關閉snapshot,開啟aof

 1 #save 900 1
 2 #save 300 10
 3 #save 60 10000
 4 
 5 appendonly  yes
 6 appendfilename zhoujy.aof
 7 # appendfsync always
 8 appendfsync everysec
 9 # appendfsync no
10 
11 no-appendfsync-on-rewrite no
12 auto-aof-rewrite-min-size 64mb

操作

 1 #重啟數據庫之前有3個key:
 2 redis 127.0.0.1:6379> keys *
 3 1) "sex"
 4 2) "age"
 5 3) "name"
 6 #修改開啟AOF參數,重啟數據庫:
 7 [email protected]:~$ ls -lh /var/lib/redis/
 8 總用量 4.0K
 9 -rw-r----- 1 redis redis  0 2013-05-25 17:41 appendonly.aof             #aof持久化已經開啟,0字節大小
10 -rw-rw---- 1 redis redis 52 2013-05-25 17:34 zhoujy.rdb                       
11 
12 redis 127.0.0.1:6379> keys *                                            #數據庫裏面沒有記錄?之前還有3個key,Why?
13 (empty list or set)
14 redis 127.0.0.1:6379> 
15 
16 #查看日誌:
17 * DB loaded from append only file: 0.000 seconds
18 發現是從0字節的aof文件裏面同步數據,為什麽不同步rdb的數據?原來redis代碼裏面寫好了優先級,AOF>RDB
19 
20 redis.c裏的代碼如下:
21 
22 void loadDataFromDisk(void) {
23     long long start = ustime();
24     if (server.aof_state == REDIS_AOF_ON) {
25         if (loadAppendOnlyFile(server.aof_filename) == REDIS_OK)
26             redisLog(REDIS_NOTICE,"DB loaded from append only file: %.3f seconds",(float)(ustime()-start)/1000000);
27     } else {
28         if (rdbLoad(server.rdb_filename) == REDIS_OK) {
29             redisLog(REDIS_NOTICE,"DB loaded from disk: %.3f seconds",
30                 (float)(ustime()-start)/1000000);
31         } else if (errno != ENOENT) {
32             redisLog(REDIS_WARNING,"Fatal error loading the DB: %s. Exiting.",strerror(errno));
33             exit(1);
34         }
35     }
36 }

這裏需要註意的是:當中途開啟AOF,重啟讓他生效的時候,千萬不能再讓他第2次正常重啟了。因為第一次重啟讓aof生效的時候,啟動redis已經讀取這個文件了,導致此時的redis數據為空的(優先級)。要是再重啟的,則會把這個空的數據save到RDB文件,這樣導致RDB原有的數據被替換,導致數據丟失。所以一定要小心,為了避免悲劇的發生,當要重啟redis的時候最好都備份下RDB文件。

 1 redis 127.0.0.1:6379> keys *
 2 (empty list or set)
 3 redis 127.0.0.1:6379> set name zhoujinyi
 4 OK
 5 redis 127.0.0.1:6379> save
 6 OK
 7 
 8 #開啟aof參數,重啟redis生效(第一次重啟)                 
 9 [email protected]:/var/lib/redis# /etc/init.d/redis-server restart
10 Stopping redis-server: redis-server stop!.
11 Starting redis-server: redis-server start!
12 [email protected]:/var/lib/redis# ls -lh #生成aof文件,已經生效
13 總用量 4.0K
14 -rw-r----- 1 root root  0  5月 26 01:12 appendonly.aof
15 -rw-rw---- 1 root root 36  5月 26 01:12 dump.rdb
16 
17 redis 127.0.0.1:6379> keys *   #如上面所說的優先級原因:aof > rdb,結果為空
18 (empty list or set)
19 
20 #再重啟(第2次正常重啟),把上面空的結果save到了RDB,數據丟失。此時的db是空的,日誌記錄 "* DB saved on disk"
21 [email protected]:/var/lib/redis# /etc/init.d/redis-server restart 22 Stopping redis-server: redis-server stop!. 23 Starting redis-server: redis-server start! 24 25 [email protected]:/var/lib/redis# ls -lh #數據已經被初始化了,數據丟失。 26 總用量 4.0K 27 -rw-r----- 1 root root 0 5月 26 01:12 appendonly.aof 28 -rw-rw---- 1 root root 18 5月 26 01:13 dump.rdb 29 redis 127.0.0.1:6379> keys * 30 (empty list or set)

這裏就有一個問題,比如在用redis的時候,剛開始只開啟RDB的持久方式,AOF沒有開啟,在跑一段時間之後想開啟AOF,那如何把RDB的數據直接寫到AOF文件呢?有2種方法:
①: 在開啟AOF之前,先執行bgrewriteaof,再重啟。

 1 redis 127.0.0.1:6379> keys *                   #查看是否有數據
 2 (empty list or set)
 3 redis 127.0.0.1:6379> set name zhoujinyi       #生成數據
 4 OK
 5 redis 127.0.0.1:6379> set sex man
 6 OK
 7 redis 127.0.0.1:6379> set age 27
 8 OK
 9 redis 127.0.0.1:6379> keys *
10 1) "name"
11 2) "sex"
12 3) "age"
13 redis 127.0.0.1:6379> bgsave                   #保存數據
14 Background saving started
15 redis 127.0.0.1:6379> keys *
16 1) "name"
17 2) "sex"
18 3) "age"
19 [email protected]:/var/lib/redis# ls -lh                 #只有一個RDB文件,沒有AOF文件
20 總用量 4.0K
21 -rw-rw---- 1 root root 52  5月 25 23:48 dump.rdb
22 
23 redis 127.0.0.1:6379> bgrewriteaof             #執行合並重寫功能,生成AOF文件
24 Background append only file rewriting started
25 
26 [email protected]:/var/lib/redis# ls -lh                 #AOF文件生成成功
27 總用量 8.0K
28 -rw-rw---- 1 root root 122  5月 25 23:49 appendonly.aof
29 -rw-rw---- 1 root root  52  5月 25 23:48 dump.rdb
30 #這時候去打開redis.conf 文件中的aof參數(appendonly yes),重啟生效。
31 [email protected]:/var/lib/redis# /etc/init.d/redis-server restart
32 Stopping redis-server: redis-server stop!
33 Starting redis-server: redis-server start! 34 35 #日誌裏面出現:* DB loaded from append only file: 0.000 seconds 36 37 redis 127.0.0.1:6379> keys * #數據還在 38 1) "sex" 39 2) "name" 40 3) "age"

②: 利用CONFIG GET/SET 的方法動態修改配置文件,和①比少了重啟的操作。

 1 redis 127.0.0.1:6379> set name zhoujinyi
 2 OK
 3 redis 127.0.0.1:6379> set sex man
 4 OK
 5 redis 127.0.0.1:6379> set age 27
 6 OK
 7 redis 127.0.0.1:6379> keys *
 8 1) "age"
 9 2) "name"
10 3) "sex"
11 redis 127.0.0.1:6379> BGSAVE
12 Background saving started
13 redis 127.0.0.1:6379> 
14 
15 [email protected]:/var/lib/redis# ls -lh                         #只有rdb文件
16 總用量 4.0K
17 -rw-rw---- 1 root root 52  5月 26 00:09 dump.rdb
18 
19 #動態修改參數,把aof功能開啟:appendonly yes
20 
21 redis 127.0.0.1:6379> CONFIG GET append*               #在線查看參數
22 1) "appendonly"
23 2) "no"
24 3) "appendfsync"
25 4) "everysec"
26 redis 127.0.0.1:6379> CONFIG SET appendonly yes        #動態修改參數
27 OK
28 redis 127.0.0.1:6379> CONFIG GET append*
29 1) "appendonly"
30 2) "yes"
31 3) "appendfsync"
32 4) "everysec"
33 redis 127.0.0.1:6379>
34 
35 [email protected]:/var/lib/redis# ls -lh                          #aof文件已經生成,並且有數據(同步rdb)。
36 總用量 8.0K
37 -rw-rw---- 1 root root 122  5月 26 00:10 appendonly.aof
38 -rw-rw---- 1 root root  52  5月 26 00:09 dump.rdb
39 
40 #日誌裏面的信息:* Background append only file rewriting started by pid 3165
41 #因為參數是動態修改的,在重啟之後會失效,所以在維護的時候修改redis.conf文件的參數即可。

從上面的結果看出,redis讀取aof的文件要先於rdb文件,所以盡量一開始開啟aof選項,不要在中途開啟。通過日誌可以很清楚的知道redis通過那個文件來取數據的:
RDB: * DB loaded from disk: 0.000 seconds
AOF: * DB loaded from append only file: 0.000 seconds
保存數據則是:
RDB:* DB saved on disk
AOF: * Calling fsync() on the AOF file.

4、redis.conf 基本配置: 開啟snapshot,開啟aof

 1 save 900 1
 2 save 300 10
 3 save 60 10000
 4  
 5 appendonly  yes
 6 appendfilename zhoujy.aof
 7  # appendfsync always
 8 appendfsync everysec
 9  # appendfsync no
10  
11 no-appendfsync-on-rewrite no
12 auto-aof-rewrite-min-size 64mb

操作

 1 #同時開啟這2個參數,在日誌裏面會記錄:
 2 * Calling fsync() on the AOF file.
 3 * DB saved on disk
 4 
 5 redis 127.0.0.1:6379> keys *
 6 (empty list or set)
 7 redis 127.0.0.1:6379> set name zhoujinyi
 8 OK
 9 redis 127.0.0.1:6379> set age 27
10 OK
11 redis 127.0.0.1:6379> set sex man
12 OK
13 redis 127.0.0.1:6379> keys *
14 1) "name"
15 2) "age"
16 3) "sex"
17 
18 [email protected]:/var/lib/redis# ls -lh   #aof,rdb 2個文件已經生成,並且aof文件大小根據操作命令實時增加,而rbd需要手動save或則到了刷寫機制的閥值才增加
19 總用量 8.0K
20 -rw-r----- 1 root root 122  5月 26 00:39 appendonly.aof
21 -rw-rw---- 1 root root  18  5月 26 00:37 dump.rdb
22 
23 redis 127.0.0.1:6379> save       #保存快照
24 OK
25 
26 [email protected]:/var/lib/redis# ls -lh   #rdb文件大小增加
27 總用量 8.0K
28 -rw-r----- 1 root root 136  5月 26 00:41 appendonly.aof
29 -rw-rw---- 1 root root  52  5月 26 00:41 dump.rdb
30 
31 redis 127.0.0.1:6379> flushall      #清除所有數據
32 OK
33 
34 [email protected]:/var/lib/redis# ls -lh      #數據清除之後,rdb文件大小初始化了,而aof文件卻增加了,Why?
35 總用量 8.0K
36 -rw-r----- 1 root root 154  5月 26 00:43 appendonly.aof
37 -rw-rw---- 1 root root  18  5月 26 00:43 dump.rdb
38 #原來aof文件記錄的是修改數據的操作,所以文件是追加形式的,flushall命令被追加到最後。
39 
40 [email protected]:/var/lib/redis# /etc/init.d/redis-server restart        #重啟,看看通過aof的載入能否被讀取到?
41 Stopping redis-server: redis-server stop!.
42 Starting redis-server: redis-server start!
43 [email protected]:/var/lib/redis# ls -lh                                  #aof文件大小不變,重啟不能初始化aof文件
44 總用量 8.0K
45 -rw-r----- 1 root root 154  5月 26 00:43 appendonly.aof
46 -rw-rw---- 1 root root  18  5月 26 00:45 dump.rdb
47 
48 redis 127.0.0.1:6379> keys *       #日誌裏面記錄“* DB loaded from append only file: 0.012 seconds”,但沒有數據,說明aof確實被初始化了。
49 (empty list or set)
50 
51 #因為數據都已經被清除了,想讓aof文件大小也初始化掉,該如何操作呢?
52 很簡單:
53 redis 127.0.0.1:6379> bgrewriteaof    #讓aof合並重寫,因為aof文件的最後一條記錄的flushall操作,前面的記錄都無效了,合並所有操作之後就初始化了。
54 Background append only file rewriting started
55 redis 127.0.0.1:6379> 
56 
57 [email protected]:/var/lib/redis# ls -lh        #aof文件被初始化
58 總用量 4.0K
59 -rw-rw---- 1 root root  0  5月 26 00:51 appendonly.aof
60 -rw-rw---- 1 root root 18  5月 26 00:45 dump.rdb

通過上面的這些測試,已經說明RDB和AOF他們的操作方式,以及如重啟時的載入,重啟時將按照以下優先級恢復數據到內存:
?如果只配置AOF,重啟時加載AOF文件恢復數據。
?如果同時 配置了RBD和AOF,啟動是只加載AOF文件恢復數據。
?如果只配置RBD,啟動是講加載dump文件恢復數據。

為了防止悲劇的發生,我們應該進行備份。

三、對Redis備份

備份很簡單,只需要把RDB,AOF的文件復制備份起來就可以了。相同版本的備份文件可以任意使用。不同版本沒有試過。

 1 #redisA: A上生成測試數據
 2 redis 127.0.0.1:6379> set name zhoujinyi
 3 OK
 4 redis 127.0.0.1:6379> set sex man
 5 OK
 6 redis 127.0.0.1:6379> set age 17
 7 OK
 8 redis 127.0.0.1:6379> keys *
 9 1) "age"
10 2) "name"
11 3) "sex"
12 redis 127.0.0.1:6379> bgsave
13 Background saving started
19 #redisB: B上沒有數據
20 redis 127.0.0.1:6380> keys *
21 (empty list or set)
22 
23 #復制A的文件到B(rdb和aof文件)
24 cp redis/* redis2/  
25 #修改權限
26 chown -R redis.redis *
27 #重啟B
28 [email protected]:~$ redis -p 6380 shutdown
29 [email protected]:~$ redis -p 6380
30 #還原成功
31 redis 127.0.0.1:6380> keys *
32 1) "sex"
33 2) "name"
34 3) "age"

以上完成。

Redis持久化磁盤IO方式及其帶來的問題   有Redis線上運維經驗的人會發現Redis在物理內存使用比較多,但還沒有超過實際物理內存總容量時就會發生不穩定甚至崩潰的問題,有人認為是基於快照方式持