Redis:記憶體為界的有狀態服務
· tech
📑 目錄
第二個有狀態的重量級是 Redis,而它跟 上一篇的 Kafka 剛好是一組完美對照:Kafka 磁碟為王,Redis 記憶體為界。兩者都有狀態,但體檢表第②題「狀態放哪」的答案不同——一個在磁碟、一個在記憶體——它們的 infra 決策就走向了完全不同的方向。
記憶體為界:硬牆在 RAM
這張圖和 Kafka 那張放在一起看,就是這系列想訓練的眼睛:同樣有狀態,但狀態的「介質」不同,瓶頸和決策就全不一樣。 Kafka 的資料在磁碟,你煩惱的是磁碟 throughput 與 TB 級容量;Redis 的資料在記憶體,你煩惱的是那道貴又硬的 RAM 牆——記憶體不像磁碟能便宜地一直加,所以 Redis 的 infra,幾乎都圍繞「怎麼在有限記憶體裡活好」打轉。
拓撲階梯:你到底需要哪一種?
Redis 的第二個核心 infra 決策,是拓撲。從單機到 Cluster 是一道階梯,每爬一階,解決一個新問題、也多一分複雜:
容量、監控、在 k8s 上
- 容量:記憶體是硬牆。設好
maxmemory+ eviction 政策,並預留 fork headroom(別讓 maxmemory 貼死實體 RAM,否則持久化一 fork 就 OOM)。 - 監控:
used_memoryvsmaxmemory(離牆多近)、eviction / expired 數、快取命中率、replication lag(replica 落後多少)、slowlog(慢命令)、連線數。記憶體使用率是我第一個看的。 - 在 k8s 上:StatefulSet + PV 放持久化檔;但重點是 memory 的
requests/limits要設對——memory 超 limit 會被 OOMKill,而 Redis 又要留 fork headroom,所以 pod 的 memory limit 得比 maxmemory 高出一截,否則持久化一觸發就被 k8s 殺掉。這是很多人「Redis 一備份就被重啟」的元兇。
反思
同樣有狀態,「狀態放哪」決定了一切
把 Kafka 和 Redis 並排體檢,是我覺得這系列最值得的一組對照。它們都在stateful 那一端,但因為狀態的介質不同——一個磁碟、一個記憶體——幾乎所有 infra 決策都分了岔:Kafka 煩惱磁碟 throughput 與 retention,Redis 煩惱 maxmemory 與 fork headroom;Kafka 擴容是搬 partition,Redis 擴容是加 replica 或上 Cluster。這讓我對體檢表第②題的威力更有感——「有沒有狀態」只是第一層,「狀態存在什麼介質上」才真正決定一個工具的脾氣。 看一個新的有狀態系統,我現在會追問到底:它的狀態是在記憶體、本地磁碟、還是遠端儲存?答案一出來,它的瓶頸、擴縮方式、故障模式就八九不離十了。
拓撲選型,是「別過度設計」的一道考題
Redis Cluster 很酷——slot 分片、自動 rebalance、水平擴展,聽起來就很「大規模」。但我看過太多團隊,資料明明幾 GB、單機記憶體綽綽有餘,卻一上來就架 Cluster,然後被 multi-key 操作的限制、slot 遷移的複雜、維運的負擔搞得焦頭爛額。Cluster 解決的是「單機記憶體裝不下」這個特定問題;如果你沒有這個問題,它帶來的只有複雜度。 大多數人真正需要的,其實只是「主從 + Sentinel」——有 HA、有讀擴展,就夠了。這道拓撲選型題,教我一個更普遍的紀律:先確認你有那個問題,再上解那個問題的方案;為了不存在的規模預先架設複雜架構,是我看過最常見、也最貴的一種過度設計。
記憶體是硬牆,而硬牆逼你面對取捨
我最喜歡 Redis 的一點,反而是它的「限制」——記憶體不像磁碟,不能便宜地一直加,所以它逼著你面對取捨:哪些資料值得放進這麼貴的記憶體?該設多長的 TTL?撞牆時要淘汰誰?這些問題,磁碟系統可以靠「再加一顆硬碟」拖延,但記憶體系統躲不掉。而我發現,正是這種「資源有硬上限」的約束,反而養出更好的設計直覺——當你不能無限擴張,你就被迫去想「什麼才是真正重要、值得留下的」。無論是記憶體、時間、還是團隊的注意力,有限的資源逼出的取捨,往往比無限的資源養出的鋪張,更接近好的工程。