iT邦幫忙

2026 iThome 鐵人賽

DAY 15
0

Day 14 最後那 5 筆沒掉,是 AOF 救回來的。

RDB 是隔一段時間拍一張照,AOF 比較像記帳:每一筆寫入指令照順序記下來,重開的時候從頭再跑一遍。

常用指令

  • CONFIG GET appendonly(有沒有開啟,預設 no)
  • CONFIG GET appendfsync(多久真的寫進硬碟一次,預設 everysec)
  • BGREWRITEAOF(重寫 AOF,幫檔案瘦身)

預設是關的

開一個全新的 Redis 試試看(在主機的終端機下,跑完會自己刪掉):

docker run --rm redis:7-alpine sh -c 'redis-server --daemonize yes > /dev/null && sleep 1 && redis-cli CONFIG GET appendonly'

https://ithelp.ithome.com.tw/upload/images/20260927/201842091bMmdl7RPh.png

我們的是 yes,因為 Day 2 的 docker-compose 有加這一行:

command: redis-server --appendonly yes # AOF 持久化

所以 Day 14 其實一直是 RDB 和 AOF 兩套一起在跑。

檔案長什麼樣

先清乾淨(BGREWRITEAOF 等等會講,先照打,在主機的終端機下):

docker exec redis30days redis-cli FLUSHALL

docker exec redis30days redis-cli BGREWRITEAOF

docker exec redis30days ls -la /data/appendonlydir

https://ithelp.ithome.com.tw/upload/images/20260927/20184209y4MU1Bk5IV.png

Redis 7 的 AOF 是一個資料夾、三個檔案:

檔案 放什麼
.base.rdb 某個時間點的完整資料
.incr.aof 那之後的每一筆寫入
.manifest 目錄,記現在該讀哪兩個檔

寫一筆,看 incr 多了什麼(在主機的終端機下):

docker exec redis30days redis-cli -n 1 SET hello world

docker exec redis30days sh -c 'cat /data/appendonlydir/*.incr.aof'

https://ithelp.ithome.com.tw/upload/images/20260927/201842099cb8m4a6pZ.png

跳過 * 跟 $ 開頭的行(Redis 自己的記號),剩下的就是 SELECT 1(切到 db1)跟剛剛打的 SET hello world。AOF 記的就是指令本身。

檔案會一直長

記帳的問題是帳本只會越來越厚。計數器加 10 萬次(在主機的終端機下):

for i in $(seq 1 100000); do echo "INCR counter"; done | docker exec -i redis30days redis-cli -n 1 --pipe

docker exec redis30days ls -la /data/appendonlydir

https://ithelp.ithome.com.tw/upload/images/20260927/20184209Wf7xJbqRJG.png

counter 現在是 100000,檔案裡卻記了 10 萬行 INCR(2.6MB)。其實一行 SET counter 100000 就夠了。

BGREWRITEAOF 就是在做這件事:照現在的資料重新產一份,不管之前是怎麼改過來的(在主機的終端機下):

docker exec redis30days redis-cli BGREWRITEAOF

docker exec redis30days ls -la /data/appendonlydir

https://ithelp.ithome.com.tw/upload/images/20260927/201842090KTCm5Nmrm.png

base 從 89 變 121 bytes(裝進了 hello 跟 counter = 100000),incr 從 2.6MB 清成 0,整個 AOF 從 2.6MB 瘦到 121 bytes。檔名的編號也跳了一號,舊的那組被刪掉了。

平常不用自己下,預設會自動重寫(在主機的終端機下):

docker exec redis30days redis-cli CONFIG GET 'auto-aof-rewrite-*'

https://ithelp.ithome.com.tw/upload/images/20260927/20184209QX8wtW5FU9.png

檔案超過 64MB 而且比上次重寫完大一倍(.rdb + .aof),就自動重寫一次。重寫也是 fork 一個副本去做,跟 Day 14 的 BGSAVE 一樣。

混合持久化

base 的副檔名是 .rdb,看一下開頭(在主機的終端機下):

docker exec redis30days sh -c 'head -c 9 /data/appendonlydir/*.base.rdb; echo; head -c 9 /data/dump.rdb; echo'

https://ithelp.ithome.com.tw/upload/images/20260927/20184209qu7ivkflTT.png

跟 Day 14 的 dump.rdb 一模一樣,因為 base 本身就是一份 RDB(aof-use-rdb-preamble 預設 yes)。

再寫一筆,然後重開看 log(在主機的終端機下):

docker exec redis30days redis-cli -n 1 INCR counter   # 這筆只在 incr 裡

docker restart redis30days

docker logs --tail 9 redis30days

https://ithelp.ithome.com.tw/upload/images/20260927/2018420990evjUZvNh.png

先讀 RDB,把 hello 跟 counter 兩個 key 載回來,再跑 incr 補上剛剛那筆 INCR,counter 就是 100001。RDB 載入快,AOF 掉得少,Redis 7 預設就是兩個一起用。

三種 fsync

「寫進檔案」其實有兩步:先交給作業系統的緩衝區,作業系統再找時間寫到硬碟。fsync 是叫它現在馬上寫。還在緩衝區的時候斷電,一樣會掉。

appendfsync 決定多久 fsync 一次:

設定 什麼時候寫進硬碟 最壞掉多少
always 每一次寫入,寫完才回 OK 不掉
everysec(預設) 每秒一次 一秒左右
no 交給作業系統 Linux 通常是 30 秒

always 一筆都不掉,那為什麼不開?拿 Day 3 的壓測比一下(在主機的終端機下):

docker exec redis30days redis-cli CONFIG SET appendfsync always

docker exec redis30days redis-benchmark -t set -n 100000 -q

docker exec redis30days redis-cli CONFIG SET appendfsync everysec

docker exec redis30days redis-benchmark -t set -n 100000 -q

https://ithelp.ithome.com.tw/upload/images/20260927/20184209Y54VzxTfOz.png

https://ithelp.ithome.com.tw/upload/images/20260927/20184209qO5UWOUAEI.png

每秒吞吐量從 19 萬掉到 3.7 萬,慢了 5 倍多。每一筆都要等硬碟寫完才能回,Day 3 說的「在記憶體裡所以快」等於沒了。這就是為什麼預設是 everysec。

為什麼要在意

  • everysec 最壞掉一秒左右,always 不掉但慢 5 倍多。 所以一筆都不能掉的東西(餘額、交易紀錄)本來就不該只放在 Redis。Redis 裡放的,要是「掉了還能從資料庫重建」的東西。
  • 原本沒開 AOF 的 Redis,直接改設定檔打開再重開,資料會全部不見。 因為 AOF 一打開,重開時就只讀 AOF、不看 dump.rdb,但這時候 AOF 裡什麼都沒有。正確順序是先下 CONFIG SET appendonly yes,讓 Redis 把現有的資料寫進 AOF,再去改設定檔。
  • 重寫跟 Day 14 的 BGSAVE 一樣要 fork。 資料越多,fork 那一下主行程卡越久;重寫期間寫入越多,多吃的記憶體越多。而且自動重寫不會先問你。

明天

持久化解決的是「重開之後資料還在」,沒解決「這台機器整個掛了」。明天來看主從複製,多開一台 Redis 當備份/images/emoticon/emoticon12.gif


上一篇
Day 14|RDB
下一篇
Day 16|主從複製
系列文
從購物車到秒殺:30 天 Redis 高併發自學筆記 共 21 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言