“兄弟,我跟你説,我今天差點當場原地昇天。”

我一屁股癱在工位上,把電腦包往桌上一丟,整個人像從 40°C 的機房裏逃出來一樣。隔壁工位的小王抬頭看了我一眼:“咋了,又面試了?”

我點點頭:“對,還是社招那套八股文。但今天這個面試官,兄弟,堪稱 Redis 分區界的李白——題目一出,直接把我送上天。”

小王哈哈一笑:“Redis 分區那玩意?”

我沉默五秒:“……對,就是這個,把我整不會了。”

於是,今天這篇文章就誕生了。希望能救你們一命,哪怕只救一個,咱都算功德無量。

接下來,小米我就用最直白、最故事的方式,把“為什麼要做 Redis 分區?有哪些方案?每種方案有哪些坑?”講得明明白白。

故事開始:Redis 為什麼需要分區?

問你個問題:

“你知道什麼時候 Redis 單實例會扛不住嗎?”

聽上去像靈魂拷問,但實際在生產中太常見了。想象一下你有一個 Redis 實例,裏面塞了幾千萬個 key,數據量 20GB、30GB 地往上漲,寫 QPS 上萬級別。有一天你發現:

  • 機器內存快滿了;
  • 單線程 CPU 飆到天花板;
  • RDB 或 AOF 時,延遲像坐火箭;
  • 重啓恢復時需要十幾分鍾;
  • 客户端操作開始一卡一卡的。

這時候,你的 Redis 就好比一個人同時扛兩個冰箱外加一袋四十斤大米,壓得嗓子都快擠不出聲了。這就是 Redis 分區要解決的根本問題:

  • 單實例容量瓶頸(內存不夠):Redis 是基於內存的,不做分區就只能靠升級機器加內存,但你總不能給它上 1TB 內存吧?
  • 單實例吞吐瓶頸(CPU 不夠):Redis 的所有命令都在單線程上執行。單線程處理能力是有限的,再怎麼優化,CPU 總有天花板。
  • 主從架構也救不了你:主從只能解決讀擴展,解決不了寫擴展,也解決不了內存問題。

所以,面試官問你:

“為什麼要 Redis 分區?”

你只需要底氣十足地回一句:

“因為 Redis 單實例有三大瓶頸:內存瓶頸、吞吐瓶頸和主從寫擴展能力不足。分區能讓我們橫向擴展 Redis,突破單節點能力限制。”

記住,有理有據,穩穩的。

Redis 分區有哪些方案?面試官最想聽你説這段

當面試官繼續問:

“那你知道 Redis 有哪幾種分區方案嗎?”

我的腦袋當時一片空白,只剩下一行代碼在閃爍。

回家回憶了一晚上,終於給你們整理出了 Redis 分區的三大主流方案,用小米的風格總結一下就:

Redis 分區可以分為 3 類:客户端分區、代理分區(中間件分片)和 Redis Cluster(服務端分片)

下面我就用一個故事,讓你徹底記住這三種設計。

客户端分區:客户端自己決定把 key 放哪

想象你有 3 個 Redis 實例:A、B、C。客户端收到一個 key,比如 “user:100”,它自己做如下步驟:

  1. 對 key 做 hash
  2. 取模
  3. 得到應該放到 A 或 B 或 C

這叫客户端分區,也是最傳統的辦法。Jedis Sharding、Redisson 的分區功能,都屬於這種方式。

優點:

  • 實現簡單;
  • 客户端直接知道 key 在哪台 Redis,不需要中轉;
  • 請求鏈路最短,性能好。

缺點致命:

  • 客户端要維護路由規則,業務代碼耦合;
  • 節點變化(遷移、擴容、縮容)要改配置;
  • key 無法跨節點操作(比如 mget、事務、lua 都不行)

總結一句:

客户端分區適合小團隊早期,簡單暴力;但隨着業務發展,會越來越痛苦。

代理分區(Proxy):Redis 上加一箇中間件幫你分片

比如:

  • Twemproxy(Twitter)
  • Codis(國內大廠用得最多)
  • Dynomite(Netflix)

這種方式是這樣玩的:

客户端 → 代理服務器 → 多個 Redis 實例

所有 key 的路由都由代理負責。客户端完全不知道 Redis 背後有多少台機器,它只需要連代理就行。

優點:

  • 對客户端透明,業務接入簡單;
  • 可動態擴容縮容;
  • 代理可以做連接池、監控、故障轉移。

缺點:

  • 多了一層代理,增加延遲;
  • 代理是額外組件,需要運維;
  • 代理本身可能成為瓶頸(除非做 Proxy 集羣)

總結一句:

Proxy 讓 Redis 分區變得可控,但你得付出複雜度和延遲代價。Codis 是其中最成熟的方案。

Redis Cluster:官方原生分區方案

2015 年之後最主流的方案。Redis Cluster 不需要代理、不需要客户端做 hash,它內部有 16384 個 hash slot。每個 master 管一部分 slot,客户端只要知道 key 屬於哪個 slot,就能直接訪問對應節點。

最妙的是:

  • 節點之間互相通信
  • 客户端自動跟隨重定向(MOVED/ASK)
  • 支持自動故障切換
  • 支持橫向擴容縮容

優點:

  • 官方方案,成熟穩定;
  • 支持自動 failover;
  • 支持動態擴容;
  • 不需要代理這一層。

缺點:

  • 無法保證多 key 操作(除非 key 在同一個 slot);
  • 運維複雜度比單實例高一些;
  • 業務必須使用 cluster 兼容客户端;
  • 對 bigkey、慢查詢處理較嚴格。

總結一句:

Redis Cluster 是目前最推薦的生產方案,兼顧擴展性和穩定性。

Redis 分區有什麼缺點?能不能在面試裏説漂亮?

當面試官問你:

“那你覺得 Redis 分區最大的缺點是什麼?”

請你千萬別回答:

  • 分區很好,沒有缺點。
  • 缺點不多。

這種回答只會讓面試官覺得你沒動過生產環境。正確答案必須包括以下幾個核心痛點:

跨節點操作受限(最大痛點)

比如:

  • mget
  • multi / exec 事務
  • lua 腳本涉及多個 key
  • rename
  • keys 命令
  • scan 全庫掃描

只要 key 分佈在不同節點,就直接涼涼。這是 Redis 分區的本質問題,任何方案都無法完美規避。

路由複雜度增加

不管是客户端、代理還是 Cluster,都需要路由規則。路由意味着:

  • 要維護節點列表
  • 要支持遷移
  • 要處理重定向
  • 要處理 hash slot

越複雜的系統,越容易出錯。

數據遷移成本高

擴容 Redis Cluster 時,遷移 slot 要佔用帶寬和機器性能。

機器本來就忙,你再遷移數據,就等於往火上澆油。

運維複雜度上升

分區意味着:

  • 多實例監控
  • 多實例故障處理
  • 多實例平衡
  • 多實例數據一致性

單實例 Redis 10 分鐘能搞定的問題,分區後可能要 2 小時。

熱點 key 問題更嚴重

你分區只是分散 key,不是分散壓力。如果有個 key 被瘋狂讀寫,比如:

  • 排行榜
  • 用户狀態
  • 高頻計數器

那這個節點依然會被打爆。

總結:面試官真正想聽到的版本

如果你在面試中被問到 Redis 分區,你可以用我下面這段“標準答案”,基本能穩穩通過。

1、面試官:為什麼要做 Redis 分區?

你:

Redis 單實例會遇到三大瓶頸:內存瓶頸、吞吐瓶頸、以及主從架構無法擴展寫能力。為了突破單節點限制,我們需要用分區的方式把數據打散到多個實例上,實現水平擴展。

別隻背八股!這篇講透 Redis 分區,讓你面試不再心虛_單實例

2、面試官:有哪些 Redis 分區方案?

你:

Redis 分區方案主要有三類:

  1. 客户端分區:客户端做 key 到節點的路由,比如 Jedis Sharding。簡單但業務耦合高。
  2. 代理分區:通過 Proxy 組件分片,比如 Codis、Twemproxy。對客户端透明,但增加延遲。
  3. Redis Cluster:官方原生分區,通過 16384 hash slot 分片。支持自動故障切換和擴容,是目前最主流最推薦的方案。

別隻背八股!這篇講透 Redis 分區,讓你面試不再心虛_單實例_02

3、面試官:Redis 分區有什麼缺點?

你:

主要有五點:

  • 跨節點操作受限(多 key 操作是最大痛點)
  • 路由規則複雜
  • 擴容遷移成本高
  • 運維難度增加
  • 熱點 key 仍可能集中在單節點

別隻背八股!這篇講透 Redis 分區,讓你面試不再心虛_單實例_03

尾聲:今天的面試,我到底翻沒翻車?

小王問我:“那你今天回答怎麼樣?”

我嘆口氣:“哈哈,兄弟,我 Redis Cluster 部分講了十分鐘,感覺面試官嘴角都上揚了。”

小王豎起大拇指:“你這不是挺厲害的嗎!”

我搖頭:“後面他問‘Redis Cluster 節點之間是怎麼感知對方存活的?廣播用啥機制?’我當場卡殼了。”

小王撲通一聲笑倒在椅子上:“這面試官太狠了!”

我攤手:“所以啊,我今天把 Redis 分區這篇文章寫出來,就是確保你們以後不會像我一樣翻車。”

END

我是小米,一個喜歡分享技術的31歲程序員。如果你喜歡我的文章,歡迎關注我的微信公眾號“軟件求生”,獲取更多技術乾貨!