「Redis 要不要上 Cluster?」這種問題我沒辦法直接回答,因為它問錯了。

Cluster、Sentinel、replica、讀寫分離——這四個東西常常被打包成一句「上 HA」,但它們解的是四個不同的問題。選錯的代價不對稱:你只是怕它掛掉,卻上了 Cluster,換來的是一整套分片運維的複雜度,去解一個你根本沒有的問題。

比較有用的問法是:你撞到的是哪一堵牆?

牆 0:怕重啟就沒了

這堵牆是 Redis 特有的,DB 天生免疫。

Redis 資料在記憶體裡,進程一重啟就空了。所以它需要 RDB(定期快照)或 AOF(追加寫入日誌),或兩者混用。關聯式資料庫沒有這個問題——WAL(write-ahead log)本來就是它的基本結構,每一筆寫入落地之前先進 log,crash 之後照 log 重放。

這堵牆跟高可用一點關係都沒有,但它常常被混進去講。一台 Redis 開了 AOF,它還是一台會掛的 Redis;你只是保證它掛完再爬起來時資料還在。

牆 1:怕它死掉(可用性)

這才是「HA」三個字真正在講的東西。而這裡有一個最常見的誤會:

Replication 給你的是副本,不是高可用。

先把三個詞講白:replication 是「把主要那台的資料持續複製到另一台」;被寫入的那台叫 primary(主庫),跟著複製的那台叫 replica(副本);而 failover 是「主庫掛了,讓副本頂上」這整套動作。

問題就出在第三個。你開了一台 replica,資料是同步過去了,但 primary 掛掉的那一刻,誰來決定 replica 升格?誰去通知客戶端改連新的位址?沒有人——有副本沒有 failover 機制,等於半夜三點你自己爬起來手動切。

所以這堵牆要兩個東西一起才算翻過去:

  • replication — 資料有副本
  • failover 機制 — Redis 是 Sentinel,PostgreSQL 是 promote 流程。它負責偵測、選出接手的那台、讓客戶端跟著改連

我自己在 express-rabbitmq 那個可靠性實驗場裡實測過兩邊:Redis 那條跑 Sentinel promote,觀察客戶端有沒有跟著轉;DB 那條跑 PostgreSQL promote,灌 20 筆資料驗證切換過程零丟失。驗過跟看過文件是兩件事——文件說會 failover,實測告訴你 failover 的那幾秒鐘客戶端是什麼反應。

牆 2:讀不夠用(讀擴展)

這堵牆有意思的地方在於:它的解法跟牆 1 是同一個東西的第二種用途。

你為了可用性開的那些 replica,反正資料都同步過去了,那就順便拿來分擔讀取——這就是讀寫分離。寫走 primary、讀走 replica。

代價是 lag。資料同步過去要時間,所以你會遇到「使用者剛改完資料,重新整理卻看到舊的」。這個情境有個名字叫 read-your-writes,處理方式是這類讀取指定回 primary,不要走 replica。

(讀寫分離在 DB 那邊的完整取捨——lag 怎麼量、哪些查詢該回 primary——寫在讀寫分離那篇。)

順帶一個我的觀察,但沒有實測數據支撐,當成推測聽就好:Redis 的讀寫分離比 DB 少用得多。我猜是因為 Redis 本來就快,讀不夠通常不是先撞到的牆——會先撞到的是下面那堵。

牆 3:裝不下、寫不動

前面三堵牆的解法都有一個共同前提:每台機器上都是完整的一份資料

這個前提在兩種情況會破:資料大到單機記憶體/磁碟裝不下,或寫入量大到單一 primary 扛不住(因為寫入永遠只能走 primary,加 replica 完全不會提升寫入能力)。

這時候要的是 sharding——把資料切開,每台只負責一部分。

Redis Cluster 的做法是先把整個 key 空間切成 16384 個格子(官方叫 slot),每個 key 照名字算出它屬於哪一格,再把這些格子分配給不同機器。要加機器就搬幾格過去,不用重算全部。關聯式資料庫做同一件事叫分庫分表——同樣是「這筆資料該去哪一台」的分配問題,只是切的單位是資料表或資料庫。

關鍵是:sharding 跟 replication 是正交的兩件事。切成四個 shard 之後,每個 shard 內部還是需要自己的 replica 加 failover,不然任何一片掛掉就是那一段資料整個不見。Redis Cluster 之所以看起來「一次解決全部」,是因為它把牆 1 的機制內建進去了,不是因為它取代了牆 1。

所以 Cluster 不是 Sentinel 的進階版

這是整篇最想講的一句。

Sentinel 和 Cluster 常常被排成一條升級路線,好像 Sentinel 是入門版、Cluster 是專業版。但它們解的是不同的牆——Sentinel 解牆 1,Cluster 解牆 3(只是順手內建了牆 1)。

你的處境該裝的裝錯的代價
資料塞得下,但不能掛replication + Sentinel/promote上 Cluster:多一整套分片運維,解一個你沒有的問題
資料塞不下 or 寫不動sharding(Cluster/分庫分表)+ 每片自己的 replica只加 replica:寫入完全沒改善,因為寫永遠走 primary

左邊那格是實務上更常見的處境,而它也是更常被裝錯的那一格。

這套框架可以搬

最後一件事,也是我覺得這個切法真正的價值:DB 和 Redis 撞的是同一組牆,只是工具名不同

RedisPostgreSQL
0 重啟丟資料RDB / AOFWAL(天生有)
1 怕死replica + Sentinelreplica + promote
2 讀不夠replica 分讀(較少用)讀寫分離
3 裝不下 / 寫不動Cluster slot 分片分庫分表

換一個技術棧的時候,要搬的是這四堵牆的框架,不是工具名

你去看訊息佇列(message broker,就是 RabbitMQ、Kafka 那類負責幫你把訊息暫存再轉交的中間人)也是同一套:訊息寫進磁碟免得重啟就沒了,是牆 0;多個節點各存一份、掛掉時推舉一台接手,是牆 1;把訊息分流到不同分區(Kafka 叫 partition,概念跟 Redis 的 slot 一樣,都是「這筆該歸哪一台管」)好讓單台不必扛全部,是牆 3。名字全都不一樣,牆是同一組。

記住牆,工具會自己對號入座。

相關