一、對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文件。
Client 也可以使用save或者bgsave命令通知redis做一次快照持久化。save操作是在主線程中保存快照的,由於redis是用一個主線程來處理所有 client的請求,這種方式會阻塞所有client請求。所以不推薦使用。另一點需要注意的是,每次快照持久化都是將內存數據完整寫入到磁盤一次,並不 是增量的只同步臟數據。如果數據量大的話,而且寫操作比較多,必然會引起大量的磁盤io操作,可能會嚴重影響性能。
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就一定會有內存快照發生。
快照持久化過程:
1.redis調用fork,現在有了子進程和父進程。 2.父進程繼續處理client請求,子進程負責將內存內容寫入到臨時文件。由於os的寫時復制機制(copy on write)父子進程會共享相同的物理頁面,當父進程處理寫請求時os會為父
進程要修改的頁面創建副本,而不是寫共享的頁面。所以子進程的地址空間內的數 據是fork時刻整個數據庫的一個快照。 3.當子進程將快照寫入臨時文件完畢后,用臨時文件替換原來的快照文件,然后子進程退出。
不足:就是一旦數據庫出現問題,那么我們的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
上面提出了RDB持久化的不足,要是不允許數據丟失,則需要用AOF來持久化。
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文件。
AOF持久化過程:
1. redis調用fork ,現在有父子兩個進程 2. 子進程根據內存中的數據庫快照,往臨時文件中寫入重建數據庫狀態的命令 3.父進程繼續處理client請求,除了把寫命令寫入到原來的aof文件中。同時把收到的寫命令緩存起來。這樣就能保證如果子進程重寫失敗的話並不會出問題。 4.當子進程把快照內容寫入已命令方式寫到臨時文件中后,子進程發信號通知父進程。然后父進程把緩存的寫命令也寫入到臨時文件。 5.現在父進程可以使用臨時文件替換老的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操作都是順序IO操作,性能都很高。而同時在通過RDB文件或者AOF日志進行數據庫恢復的時候,也是順序的讀取數據加載到內存中。所以也不會造成磁盤的隨機讀。
到底選擇什么呢?下面是來自官方的建議:
通常,如果你要想提供很高的數據保障性,那么建議你同時使用兩種持久化方式。如果你可以接受災難帶來的幾分鍾的數據丟失,那么你可以僅使用RDB。
很多用戶僅使用了AOF,但是我們建議,既然RDB可以時不時的給數據做個完整的快照,並且提供更快的重啟,所以最好還是也使用RDB。
在數據恢復方面:
RDB的啟動時間會更短,原因有兩個:
一是RDB文件中每一條數據只有一條記錄,不會像AOF日志那樣可能有一條數據的多次操作記錄。所以每條數據只需要寫一次就行了。
另一個原因是RDB文件的存儲格式和Redis數據在內存中的編碼格式是一致的,不需要再進行數據編碼工作,所以在CPU消耗上要遠小於AOF日志的加載。
注意:
上面說了RDB快照的持久化,需要注意:在進行快照的時候(save),fork出來進行dump操作的子進程會共享父進程的內存(真正的copy-on-write)。比如機器8G內存,Redis已經使用了6G內存,這時新操作100M的內存,save的話會再多生成100M(放到緩沖區里),總共進行RDB的時候會多出100M,既6.1G的內存。
目前,通常的設計思路是利用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 zhoujy@zhoujy:~$ ls -lh /var/lib/redis/ #rdb文件初始化大小 15 總用量 4.0K 16 -rw-rw---- 1 redis redis 18 2013-05-25 16:19 zhoujy.rdb 17 zhoujy@zhoujy:~$ redis 18 redis 127.0.0.1:6379> save #保存,進行持久化,每執行一次save,會在日至里面記錄一條:“ * DB saved on disk ” 19 OK 20 redis 127.0.0.1:6379> 21 zhoujy@zhoujy:~$ 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 zhoujy@zhoujy:~$ sudo /etc/init.d/redis-server restart 35 Stopping redis-server: redis-server. 36 Starting redis-server: redis-server. 37 zhoujy@zhoujy:~$ 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 zhoujy@zhoujy:~$ sudo kill -9 21250 70 zhoujy@zhoujy:~$ redis 71 Could not connect to Redis at 127.0.0.1:6379: Connection refused 72 not connected> 73 zhoujy@zhoujy:~$ sudo /etc/init.d/redis-server start 74 Starting redis-server: redis-server. 75 zhoujy@zhoujy:~$ 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>
總結1:從上面的結果看出,開啟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 zhoujy@zhoujy:~$ 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 zhoujy@zhoujy:~$ 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>
總結2: 從上面的結果看出,關閉持久化,只有在手動save的時候數據都會被持久化,正常關閉的時候數據丟失。要是從一開始到關閉寫入數據的期間沒有手動save,則數據全部丟失!既然能手動save間接的說明了快照一直都存在,所以不能說是禁止snapshot,應該是禁止自動snapshot功能。
通過1,2驗證了之前說的:一旦數據庫出現問題,那么我們的RDB文件中保存的數據並不是全新的,下面看看AOF。
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 zhoujy@zhoujy:~$ 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 root@m2:/var/lib/redis# /etc/init.d/redis-server restart 10 Stopping redis-server: redis-server stop!. 11 Starting redis-server: redis-server start! 12 root@m2:/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 root@m2:/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 root@m2:/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 root@m2:/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 root@m2:/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 root@m2:/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 root@m2:/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 root@m2:/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文件的參數即可。
總結3: 從上面的結果看出,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 root@m2:/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 root@m2:/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 root@m2:/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 root@m2:/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 root@m2:/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 root@m2:/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 zhoujy@m2:~$ redis -p 6380 shutdown 29 zhoujy@m2:~$ redis -p 6380 30 #還原成功 31 redis 127.0.0.1:6380> keys * 32 1) "sex" 33 2) "name" 34 3) "age"
以上完成。