Redis持久化和備份資料
阿新 • • 發佈:2018-11-25
一、持久化
實現持久化的方式有兩種RDB、AOF
基於RDB方式做持久化
RDB是基於快照模式實現的,所儲存的資料檔案預設dump.rdb,具體產生這個資料檔案的方式有兩種:
方式1:客戶端執行save或者bgsave命令
- 用save方式你的話,是在主執行緒中儲存快照,也就是說在save執行完成之前所有的操作都會被阻塞,因為這是同步儲存的。
- 在執行save儲存資料的時候,不是做增量儲存,而是將記憶體中的全部資料做一次同步,所以這個過程會很慢。
- 用bgsave的話,這個是基於非同步的方式,也就是執行這個命令以後,會立刻告訴你已經執行啟動,但是不會阻塞使用者,而是在後臺悄悄的執行。
方式2:提前做好計劃任務
- 基於計劃任務自動做同步的話,是在子程序中實現。具體過程是子程序會會開啟一個檔案,將資料儲存到這個新檔案中,在完成以後改名為dump.rdb就可以了。
基於AOF方式做持久化
相對而言,AOF模式比RDB更為可靠。這種方式之所以可靠是因為快照的方式是週期性的,比如每隔10秒做一次,但是如果在做了一次持久化之後,還沒有到下一次系統就崩潰了,那麼這段時間的資料就丟失了。
AOF有有點類似於mysql的二進位制日誌,這個檔案會記錄下每次所執行的語句(主要是寫操作),每次的操作都會追加到檔案的末尾。當Redis重啟的時候,可以通過aof檔案中的命令實現在記憶體中重建資料庫。
但是aof這種方式也是有缺點的:
- 可能會有很多重複的內容,比如執行100次incre,檔案就會記錄100條,這明顯是不合理的(事實上redis程序會掃描aof中重複的事件,並進行合併)
- aof檔案會變得越來越大,為了解決這個問題,redis提供了一個命令BGREWRITEAOF,通過這個命令可以實現AOF檔案的重寫,需要注意的是這種重寫機制是比較特殊的,因為在重寫的時候,是不會去讀取原來的aof檔案,而是直接讀取記憶體中的資料,將記憶體中的資料生成一個指令集,並將指令集儲存在一個臨時檔案,在這個臨時檔案儲存完成之後,就會用這個歷史檔案去替換原來的那個aof檔案,完成重寫aof檔案的過程。so,aof檔案可以通過重寫的方式將其變小。
重寫過程:
- Redis主程序通過fork建立子程序;
- 子程序根據Redis記憶體中的資料建立資料庫重建命令序列於臨時檔案中;
- 父程序繼承 client的請求,並會把這些請求中的寫操作繼續追加到原來的aof檔案,額外地,這些新的寫請求還會被防止於一個新的緩衝佇列中;
- 子程序重寫完成,會通知父程序,父程序把緩衝中的命令寫到臨時檔案中
- 父程序用臨時檔案替代aof檔案;
相關配置
- 與RDB相關的配置
# 設定同步週期
save 900 1
save 300 10
save 60 10000
# 進行快照備份的時候,一旦監控到持久化發生了錯誤,是否停止下來
stop-writes-on-bgsave-error yes
# rdb檔案是否執行壓縮來節省空間
rdbcompression yes
# 是否校驗rdb檔案
rdbchecksum yes
# rdb檔案的檔名
dbfilename dump.rdb
# rdb檔案的位置
dir /var/lib/redis
- 與AOF相關的配置
# 指定是否啟用aof持久化
appendonly yes
# 當aof檔案的大小增長了指定比例的時候,執行一次重寫操作
auto-aof-rewrite-percentage 100
# 指定aof檔案做重寫最小值
auto-aof-rewrite-min-size 64mb
# aof持久化資訊儲存在哪個檔案中(相當於mysql的二進位制日誌檔案)
appendfilename "appendonly.aof"
# 一旦執行了操作,會立刻將操作的語句記錄到aof檔案中
# appendfsync always
# 每秒向aof檔案進行一次寫入操作
appendfsync everysec
# 不主動向aof執行寫入操作,由系統自行判斷何時向磁碟執行寫入操作
# appendfsync no
#在做重寫的時候,新的寫操作不做fsync
no-appendfsync-on-rewrite no
# 當aof檔案備被損壞時,redis返回錯誤並推出
aof-load-truncated yes
實際生產環境中肯定是同時使用rdb和aof的,那麼就會有一個問題,就是如果在某個時間點同時出發了AOF和RDB持久化,那麼會對磁碟熊帶來很大的壓力,所以通常我們的Redis會禁止同時做持久化操作,如果正在做RDB的持久化,那麼及時此時觸發了AOF的持久化也是不會執行的。
二、備份
- 在有持久化的情況下,資料會自動儲存在檔案中,這裡為了演示現將持久化關閉。
# 修改配置檔案
[[email protected] ~]# vim /etc/redis.conf
# 禁止快照方式的持久儲存
save ""
#save 900 1
#save 300 10
#save 60 10000
# 禁止AOF方式的持久儲存
appendonly no
- 刪除之前的資料,並重啟服務
[[email protected] ~]# rm -rf /var/lib/redis/dump.rdb
[[email protected] ~]# systemctl restart redis
- 在redis中填充一些資料
10.220.5.171:6379> DBSIZE
(integer) 0
10.220.5.171:6379> set name cx
OK
10.220.5.171:6379> set age 20
OK
10.220.5.171:6379> set addr tianjin
OK
10.220.5.171:6379> DBSIZE
(integer) 3
- 退出redis,再重新進入發現這些key依然存在(這些值是存在記憶體中的)
10.220.5.171:6379> exit
[[email protected] ~]# redis-cli -h 10.220.5.171
10.220.5.171:6379> DBSIZE
(integer) 3
- 但是如果重啟Redis這些資料就沒有了
10.220.5.171:6379> exit
[[email protected] ~]# systemctl restart redis
[[email protected] ~]# redis-cli -h 10.220.5.171
10.220.5.171:6379> DBSIZE
(integer) 0
- 重新插入資料,並手動執行儲存
10.220.5.171:6379> DBSIZE
(integer) 0
10.220.5.171:6379> set name cx
OK
10.220.5.171:6379> set age 20
OK
10.220.5.171:6379> set addr tianjin
OK
10.220.5.171:6379> save
OK
- 可以看到生成了新的資料檔案
[[email protected] ~]# ls /var/lib/redis/
dump.rdb
- 而我們做備份工作的時候,其實就是備份的這個檔案,現在我將這個檔案備份到tmp下
[[email protected] ~]# cp /var/lib/redis/dump.rdb /tmp/
- 模擬故障,將
/var/lib/redis/dump.rdb
刪除並重啟redis,可以看到資料已經沒有了,不過不要慌我們做了備份
[[email protected] ~]# rm -rf /var/lib/redis/dump.rdb
[[email protected] ~]# systemctl restart redis
[[email protected] ~]# redis-cli -h 10.220.5.171
10.220.5.171:6379> DBSIZE
(integer) 0
- 將備份資料挪回來,重啟Redis檢視資料
[[email protected] ~]# cp /tmp/dump.rdb /var/lib/redis/
[[email protected] ~]# ls /var/lib/redis/
dump.rdb
[[email protected] ~]# systemctl restart redis
[[email protected] ~]# redis-cli -h 10.220.5.171
10.220.5.171:6379> DBSIZE
(integer) 3
通過上面的操作很明顯的我們看到了備份資料和恢復資料的過程,在企業中資料備份也是很重要的一份工作。
------做運維之前很矯情的小年輕-----