Redis 持久化概述
Redis 是一款記憶體資料庫,所有資料預設儲存於記憶體中。然而,若伺服器重新啟動或發生故障,記憶體中的資料將會遺失。為了解決這個問題,Redis 提供了持久化機制,將記憶體中的資料保存到硬碟上。
Redis 持久化的重要性
- 資料安全:防止伺服器重啟或故障時資料遺失
- 災難復原:可從備份檔案還原資料
- 資料遷移:便於將資料轉移到其他伺服器
Redis 提供的持久化方式
Redis 提供三種持久化策略:
- RDB(Redis Database):定時將記憶體中的資料快照儲存為二進位檔案
- AOF(Append Only File):將每個寫入操作以日誌方式記錄
- 混合持久化:結合 RDB 和 AOF 的優點(Redis 4.0+)
RDB 快照機制
RDB 是 Redis 預設的持久化方式。它會在指定的時間間隔內,將記憶體中的資料集快照寫入硬碟,產生一個 dump.rdb 檔案。
RDB 運作原理
- Redis 主程序 fork 一個子程序
- 子程序將資料集寫入臨時 RDB 檔案
- 寫入完成後,用臨時檔案取代舊的 RDB 檔案
- 子程序退出,主程序繼續處理請求
RDB 優點
- 檔案緊湊:RDB 是壓縮的二進位格式,檔案較小
- 還原速度快:適合大規模資料還原
- 效能影響小:由子程序處理,不影響主程序效能
- 適合備份:適合定期備份和災難復原
RDB 缺點
- 資料遺失風險:兩次快照之間的資料可能遺失
- fork 耗時:大資料集 fork 可能造成短暫阻塞
RDB 設定參數
編輯 Redis 設定檔 /etc/redis/redis.conf:
1
| sudo nano /etc/redis/redis.conf
|
自動觸發條件
1
2
3
4
5
6
7
8
9
10
11
| # 在 900 秒(15 分鐘)內,如果至少有 1 個 key 被修改,則觸發 RDB 快照
save 900 1
# 在 300 秒(5 分鐘)內,如果至少有 10 個 key 被修改,則觸發 RDB 快照
save 300 10
# 在 60 秒(1 分鐘)內,如果至少有 10000 個 key 被修改,則觸發 RDB 快照
save 60 10000
# 如要停用 RDB,可註解以上所有 save 指令或設定:
# save ""
|
RDB 檔案設定
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| # RDB 檔案名稱
dbfilename dump.rdb
# RDB 檔案儲存目錄
dir /var/lib/redis
# 背景儲存失敗時,停止接受寫入(建議保持 yes)
stop-writes-on-bgsave-error yes
# 是否壓縮 RDB 檔案(使用 LZF 壓縮)
rdbcompression yes
# 是否在載入 RDB 時檢查檔案完整性
rdbchecksum yes
|
手動觸發 RDB 快照
1
2
3
4
5
6
7
8
| # 同步儲存(會阻塞 Redis)
redis-cli SAVE
# 非同步儲存(背景執行,推薦使用)
redis-cli BGSAVE
# 查看最後一次 RDB 快照時間
redis-cli LASTSAVE
|
AOF 日誌機制
AOF(Append Only File)持久化會記錄伺服器執行的所有寫入命令,並在伺服器啟動時重新執行這些命令來還原資料。
AOF 運作原理
- 客戶端發送寫入命令
- Redis 執行命令並更新記憶體
- 將命令追加寫入 AOF 緩衝區
- 根據設定的同步策略,將緩衝區內容寫入 AOF 檔案
AOF 優點
- 資料安全性高:可設定每秒或每次寫入同步
- 可讀性佳:AOF 是純文字格式,便於閱讀和修復
- 彈性較高:可對 AOF 檔案進行編輯和修復
AOF 缺點
- 檔案較大:AOF 檔案通常比 RDB 檔案大
- 還原速度慢:需要重新執行所有命令
- 寫入效能:頻繁的磁碟 I/O 可能影響效能
AOF 設定參數
啟用 AOF
1
2
3
4
5
6
7
8
| # 啟用 AOF 持久化(預設為 no)
appendonly yes
# AOF 檔案名稱
appendfilename "appendonly.aof"
# AOF 檔案儲存目錄(與 RDB 共用)
dir /var/lib/redis
|
同步策略
1
2
3
4
5
6
7
8
9
10
| # 同步策略設定(三選一)
# always:每次寫入都同步到磁碟(最安全,但效能最低)
# appendfsync always
# everysec:每秒同步一次(預設值,兼顧安全與效能)
appendfsync everysec
# no:由作業系統決定何時同步(效能最高,但可能遺失較多資料)
# appendfsync no
|
同步策略比較
| 策略 | 寫入效能 | 資料安全性 | 可能遺失資料 |
|---|
| always | 較慢 | 最高 | 最多 1 個命令 |
| everysec | 中等 | 較高 | 最多 1 秒資料 |
| no | 最快 | 較低 | 依系統而定 |
AOF 重寫
隨著時間推移,AOF 檔案會越來越大。Redis 提供 AOF 重寫機制,可以產生一個較小的 AOF 檔案。
AOF 重寫原理
AOF 重寫不是讀取舊的 AOF 檔案,而是:
- Redis fork 一個子程序
- 子程序根據目前記憶體中的資料,產生新的 AOF 檔案
- 主程序將重寫期間的新命令寫入緩衝區
- 子程序完成後,將緩衝區內容追加到新檔案
- 用新檔案取代舊檔案
AOF 重寫設定
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| # 當 AOF 檔案大小超過上次重寫後大小的 100% 時觸發重寫
auto-aof-rewrite-percentage 100
# AOF 檔案最小重寫大小(避免檔案太小時頻繁重寫)
auto-aof-rewrite-min-size 64mb
# 重寫時是否停用 fsync(可提高重寫效能,但降低安全性)
no-appendfsync-on-rewrite no
# 載入 AOF 時,若發現檔案末端損壞是否繼續載入
aof-load-truncated yes
# 是否使用 RDB 前導的 AOF 格式(混合持久化,Redis 4.0+)
aof-use-rdb-preamble yes
|
手動觸發 AOF 重寫
1
2
3
4
5
| # 背景執行 AOF 重寫
redis-cli BGREWRITEAOF
# 查看 AOF 相關資訊
redis-cli INFO persistence
|
RDB vs AOF 比較
| 特性 | RDB | AOF |
|---|
| 檔案格式 | 二進位 | 純文字 |
| 檔案大小 | 較小 | 較大 |
| 還原速度 | 較快 | 較慢 |
| 資料安全性 | 較低 | 較高 |
| 寫入效能 | 較高 | 較低 |
| 可讀性 | 不可讀 | 可讀 |
| 適用場景 | 備份、災難復原 | 即時資料保護 |
選擇建議
- 只用 RDB:可接受數分鐘的資料遺失,重視備份和還原速度
- 只用 AOF:需要較高的資料安全性,可接受較慢的還原速度
- 混合使用:同時啟用兩者,獲得最佳的資料安全性和還原速度(推薦)
混合持久化
Redis 4.0 引入混合持久化模式,結合 RDB 和 AOF 的優點。
混合持久化原理
在 AOF 重寫時:
- 將目前資料以 RDB 格式寫入 AOF 檔案開頭
- 後續的增量命令以 AOF 格式追加
- 還原時先載入 RDB 部分,再執行 AOF 命令
啟用混合持久化
1
2
3
4
5
| # 啟用 AOF
appendonly yes
# 啟用混合持久化(預設為 yes)
aof-use-rdb-preamble yes
|
混合持久化優點
- 還原速度快:RDB 部分可快速載入
- 資料安全性高:AOF 部分記錄增量變更
- 檔案較小:RDB 壓縮 + 增量 AOF
備份與還原
備份 RDB 檔案
1
2
3
4
5
6
7
8
| # 建立備份目錄
sudo mkdir -p /backup/redis
# 觸發 RDB 快照
redis-cli BGSAVE
# 等待快照完成後複製檔案
sudo cp /var/lib/redis/dump.rdb /backup/redis/dump_$(date +%Y%m%d_%H%M%S).rdb
|
自動備份腳本
建立備份腳本 /usr/local/bin/redis-backup.sh:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| #!/bin/bash
REDIS_DIR="/var/lib/redis"
BACKUP_DIR="/backup/redis"
DATE=$(date +%Y%m%d_%H%M%S)
RETENTION_DAYS=7
# 建立備份目錄
mkdir -p $BACKUP_DIR
# 觸發 RDB 快照
redis-cli BGSAVE
# 等待快照完成
sleep 10
# 複製 RDB 檔案
cp $REDIS_DIR/dump.rdb $BACKUP_DIR/dump_$DATE.rdb
# 複製 AOF 檔案(如果存在)
if [ -f "$REDIS_DIR/appendonly.aof" ]; then
cp $REDIS_DIR/appendonly.aof $BACKUP_DIR/appendonly_$DATE.aof
fi
# 刪除過期備份
find $BACKUP_DIR -name "dump_*.rdb" -mtime +$RETENTION_DAYS -delete
find $BACKUP_DIR -name "appendonly_*.aof" -mtime +$RETENTION_DAYS -delete
echo "Redis backup completed: $DATE"
|
設定執行權限並加入排程:
1
2
3
4
5
6
7
8
| # 設定執行權限
sudo chmod +x /usr/local/bin/redis-backup.sh
# 編輯 crontab
sudo crontab -e
# 每天凌晨 3 點執行備份
0 3 * * * /usr/local/bin/redis-backup.sh >> /var/log/redis-backup.log 2>&1
|
還原資料
從 RDB 還原
1
2
3
4
5
6
7
8
9
10
11
| # 停止 Redis 服務
sudo systemctl stop redis-server
# 複製備份檔案
sudo cp /backup/redis/dump_YYYYMMDD_HHMMSS.rdb /var/lib/redis/dump.rdb
# 設定正確的權限
sudo chown redis:redis /var/lib/redis/dump.rdb
# 啟動 Redis 服務
sudo systemctl start redis-server
|
從 AOF 還原
1
2
3
4
5
6
7
8
9
10
11
| # 停止 Redis 服務
sudo systemctl stop redis-server
# 複製備份檔案
sudo cp /backup/redis/appendonly_YYYYMMDD_HHMMSS.aof /var/lib/redis/appendonly.aof
# 設定正確的權限
sudo chown redis:redis /var/lib/redis/appendonly.aof
# 啟動 Redis 服務
sudo systemctl start redis-server
|
修復損壞的 AOF 檔案
1
2
| # 檢查 AOF 檔案
redis-check-aof --fix /var/lib/redis/appendonly.aof
|
檢查 RDB 檔案
1
2
| # 檢查 RDB 檔案完整性
redis-check-rdb /var/lib/redis/dump.rdb
|
生產環境建議設定
以下是建議的生產環境持久化設定:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| # RDB 設定
save 900 1
save 300 10
save 60 10000
dbfilename dump.rdb
dir /var/lib/redis
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
# AOF 設定
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble yes
|
重新載入設定:
1
| sudo systemctl restart redis-server
|
參考資料