Redis 企業級數據備份方案
企業級的持久化的配置策略
在實際生產環境,RDB 和 AOF 一定都要打開,RDB 和 AOF 的配置需要根據業務的數據量決定
Redis RDB 持久化配置和數據恢復實驗
RDB 持久化配置
-
自動方式
RDB 持久化在 redis.conf 文件中配置,目前配置文件存放在 /etc/redis/6379.conf,打開配置文件,添加 save 屬性配置,定期生成 RDB 快照。
# 每隔15分鐘,如果有超過1個key發生了變更,那麼就生成一個新的dump.rdb文件
save 900 1
# 每隔5分鐘,如果有超過300個key發生了變更,那麼就生成一個新的dump.rdb文件
save 300 10
# 每隔1分鐘,如果有超過10000個key發生了變更,那麼就生成一個新的dump.rdb文件
save 60 10000
save 屬性可以設置多個,就是設置多個 SNAPSHOTTING 檢查點,每到一個檢查點,就會去 check 一下,是否有指定的 key 數量發生了變更,如果有,就生成一個新的 dump.rdb 文件。
-
手動方式
也可以在 redis-cli 命令中輸入 save 或者 bgsave 命令,手動同步或異步生成 RDB 快照。
RDB 持久化機制的工作流程
-
Redis 根據配置自己嘗試去生成 RDB 快照文件;
-
fork 一個子進程出來;
-
子進程嘗試將數據 dump 到臨時的 RDB 快照文件中;
-
完成 RDB 快照文件的生成之後,就替換之前的舊的快照文件;
基於 RDB 持久化機制的數據恢復實驗
通過 redis-cli SHUTDOWN 這種方式去停掉 Redis,其實是一種安全退出的模式,Redis 在退出的時候會將內存中的數據立即生成一份完整的 RDB 快照,存放在 /var/redis/6379/dump.rdb。
需要使用 kill -9 *** 強制殺死進程的方式來模擬 Redis 異常退出。執行步驟如下:
-
先往 Redis 中插入幾條數據;
-
kill -9 強制殺死 Redis 進程,刪除 /var/run/redis_6379.pid 文件,再重新啓動 Redis;
-
通過 redis-cli 客戶端查看剛剛插入的數據,發現最新的幾條數據已經丟失;
-
配置 save 檢查點,save 5 1(每隔 5 秒,如果有超過 1 個 key 發生了變更,那麼就生成一個新的 dump.rdb 文件);
-
往 Redis 中插入幾條數據,暫停 5 秒以上;
-
kill -9 強制殺死 Redis 進程,刪除 /var/run/redis_6379.pid 文件,再重新啓動 Redis;
-
通過 redis-cli 客戶端查看剛剛插入的數據,發現最新的幾條數據還在,查看 dump 文件,發現已經更新爲成最新的了;
Redis AOF 持久化配置和相關實驗
AOF 持久化配置
AOF 持久化配置,默認是關閉的,默認打開的是 RDB 持久化配置。AOF 持久化在 redis.conf 文件中配置,目前配置文件存放在 /etc/redis/6379.conf。
打開配置文件,修改 appendonly 屬性爲 yes ,打開 AOF 持久化配置:
appendonly yes
AOF 有三種 fsync 策略:
# 每次寫入一條數據就執行一次 fsync
# appendfsync always
# 每隔一秒執行一次 fsync
appendfsync everysec
# 不主動執行fsync
# appendfsync no
-
always:每次寫入一條數據,立即將這個數據對應的寫日誌 fsync 到磁盤上去,性能非常差,吞吐量很低;
-
everysec:每秒將 os cache 中的數據 fsync 到磁盤,這個最常用的,生產環境一般都這麼配置,性能很高,QPS 還是可以上萬的;
-
no:Redis 只負責將數據寫入 os cache 就不管了,後面 os cache 根據自己的策略將數據刷入磁盤,不可控制;
基於 AOF 持久化機制的數據恢復實驗
-
設置 appendonly 屬性爲 yes,打開 AOF 持久化,重啓 Redis;
-
往 Redis 中寫入幾條數據,等待一秒;
-
kill -9 強制殺死 Redis 進程,刪除 /var/run/redis_6379.pid 文件,再重新啓動 Redis;
-
通過 redis-cli 客戶端查看剛剛插入的數據,發現最新的幾條數據還在,查看 /var/redis/6379 文件夾,發現已經存在 appendonly.aof 文件;
AOF rewrite 操作
Redis 中的內存中的數據是有一定限量的,內存到一定大小後,Redis 就會使用緩存淘汰算法(LRU)自動將一部分過期數據從內存中清除。AOF 是存放沒有寫命令的,所以文件會不斷膨脹,當大到一定的時候,AOF 會做 rewrite 操作。
在 redis.conf 文件中,可以配置 rewrite 策略。
# 如果 AOF 日誌文件增長的比例,超過了之前的100%,就可能會去觸發一次 rewrite
auto-aof-rewrite-percentage 100
# 但是此時還要去跟min-size比較,大於64M纔會去觸發一次 rewrite
auto-aof-rewrite-min-size 64mb
AOF rewrite 操作步驟:
-
Redis fork 一個子進程;
-
子進程基於當前內存中的數據,構建日誌,開始往一個新的臨時的 AOF 文件中寫入日誌;
-
Redis 主進程,接收到 client 新的寫操作之後,在內存中寫入日誌,同時新的日誌也繼續寫入舊的 AOF 文件;
-
子進程寫完新的日誌文件之後,Redis 主進程將內存中的新日誌再次追加到新的 AOF 文件中;
-
用新的日誌文件替換掉舊的日誌文件;
AOF 破損文件的修復
如果 Redis 在 append 數據到 AOF 文件時,機器宕機了,可能會導致 AOF 文件破損,用 redis-check-aof --fix 命令來修復破損的 AOF 文件。
redis-check-aof --fix /usr/local/appendonly.aof
AOF 和 RDB 同時工作
-
如果 RDB 在執行 snapshotting 操作,那麼 Redis 不會執行 AOF rewrite; 如果 Redis 再執行 AOF rewrite,那麼就不會執行 RDB snapshotting
-
如果 RDB 在執行 snapshotting,此時用戶執行 BGREWRITEAOF 命令,那麼等 RDB 快照生成之後,纔會去執行 AOF rewrite
-
同時有 RDB snapshot 文件和 AOF 日誌文件,那麼 Redis 重啓的時候,會優先使用 AOF 進行數據恢復,因爲其中的日誌更完整
企業級的數據備份方案
-
寫 crontab 定時調度腳本做數據備份
-
每小時都 copy 一份 rdb 的備份,到一個目錄中去,僅僅保留最近 48 小時的備份
-
每天都保留一份當日的 rdb 的備份,到一個目錄中去,僅僅保留最近 1 個月的備份
-
每次 copy 備份的時候,都把太舊的備份給刪了
-
每天晚上將當前服務器上所有的數據備份,發送一份到遠程的雲服務上去
按小時備份
redis_rdb_copy_hourly.sh
#!/bin/sh
cur_date=`date +%Y%m%d%k`
rm -rf /usr/local/redis/snapshotting/$cur_date
mkdir /usr/local/redis/snapshotting/$cur_date
cp /var/redis/6379/dump.rdb /usr/local/redis/snapshotting/$cur_date
del_date=`date -d -48hour +%Y%m%d%k`
rm -rf /usr/local/redis/snapshotting/$del_date
每小時 copy 一次備份,刪除 48 小時前的數據。
crontab -e
0 * * * * sh /usr/local/redis/copy/redis_rdb_copy_hourly.sh
按天備份
redis_rdb_copy_daily.sh
#!/bin/sh
cur_date=`date +%Y%m%d`
rm -rf /usr/local/redis/snapshotting/$cur_date
mkdir /usr/local/redis/snapshotting/$cur_date
cp /var/redis/6379/dump.rdb /usr/local/redis/snapshotting/$cur_date
del_date=`date -d -1month +%Y%m%d`
rm -rf /usr/local/redis/snapshotting/$del_date
每天 copy 一次備份,刪除一個月前的數據。
crontab -e
0 * * * * sh /usr/local/redis/copy/redis_rdb_copy_hourly.sh
0 0 * * * sh /usr/local/redis/copy/redis_rdb_copy_daily.sh
數據恢復方案
-
如果是 Redis 進程掛掉,那麼重啓 Redis 進程即可,直接基於 AOF 日誌文件恢復數據;
-
如果是 Redis 進程所在機器掛掉,那麼重啓機器後,嘗試重啓 Redis 進程,嘗試直接基於 AOF 日誌文件進行數據恢復;
-
如果 Redis 當前最新的 AOF 和 RDB 文件出現了丟失 / 損壞,那麼可以嘗試基於該機器上當前的某個最新的 RDB 數據副本進行數據恢復;
恢復步驟參考如下:
-
停止 Redis
-
在 Redis 配置文件中關閉 AOF 持久化配置
-
拷貝雲服務上最新的 RDB 備份數據到 /var/redis/6379 文件夾下
-
重啓 Redis,確認數據恢復
-
直接在命令行熱修改 Redis 配置,config set appendonly yes
-
確認在 /var/redis/6379 文件夾下生成 AOF 持久化文件 appendonly.aof
-
停止 Redis
-
在 Redis 配置文件中打開 AOF 持久化配置
-
重啓 Redis,確認數據情況
-
如果當前機器上的所有 RDB 文件全部損壞,那麼從遠程的雲服務上拉取最新的 RDB 快照回來恢復數據
-
如果是發現有重大的數據錯誤,比如某個小時上線的程序一下子將數據全部污染了,數據全錯了,那麼可以選擇某個更早的時間點,對數據進行恢復
舉個例子,12 點上線了代碼,發現代碼有 bug,導致代碼生成的所有的緩存數據全部錯了,找到一份 11 點的 rdb 的冷備,然後按照上面的步驟,去恢復到 11 點的數據,就可以了。
source: //www.yuque.com/yinjianwei/vyrvkf/hm1goc
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/S8zvzIyxcDVdWLe6KnYQ3w