“兄弟,我跟你説,我今天差點當場原地昇天。”
我一屁股癱在工位上,把電腦包往桌上一丟,整個人像從 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”,它自己做如下步驟:
- 對 key 做 hash
- 取模
- 得到應該放到 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 單實例會遇到三大瓶頸:內存瓶頸、吞吐瓶頸、以及主從架構無法擴展寫能力。為了突破單節點限制,我們需要用分區的方式把數據打散到多個實例上,實現水平擴展。
2、面試官:有哪些 Redis 分區方案?
你:
Redis 分區方案主要有三類:
- 客户端分區:客户端做 key 到節點的路由,比如 Jedis Sharding。簡單但業務耦合高。
- 代理分區:通過 Proxy 組件分片,比如 Codis、Twemproxy。對客户端透明,但增加延遲。
- Redis Cluster:官方原生分區,通過 16384 hash slot 分片。支持自動故障切換和擴容,是目前最主流最推薦的方案。
3、面試官:Redis 分區有什麼缺點?
你:
主要有五點:
- 跨節點操作受限(多 key 操作是最大痛點)
- 路由規則複雜
- 擴容遷移成本高
- 運維難度增加
- 熱點 key 仍可能集中在單節點
尾聲:今天的面試,我到底翻沒翻車?
小王問我:“那你今天回答怎麼樣?”
我嘆口氣:“哈哈,兄弟,我 Redis Cluster 部分講了十分鐘,感覺面試官嘴角都上揚了。”
小王豎起大拇指:“你這不是挺厲害的嗎!”
我搖頭:“後面他問‘Redis Cluster 節點之間是怎麼感知對方存活的?廣播用啥機制?’我當場卡殼了。”
小王撲通一聲笑倒在椅子上:“這面試官太狠了!”
我攤手:“所以啊,我今天把 Redis 分區這篇文章寫出來,就是確保你們以後不會像我一樣翻車。”
END
我是小米,一個喜歡分享技術的31歲程序員。如果你喜歡我的文章,歡迎關注我的微信公眾號“軟件求生”,獲取更多技術乾貨!