大家好,我是小米,一個 31 歲、依然在互聯網行業打怪升級的技術人。
今天要跟你聊一個我在 社招面試中差點翻車的問題:
“Redis 集羣模式下,如何選擇數據庫?為什麼很多項目只能用 0 號庫?”
這個看似簡單,卻能把無數 Java 工程師搞得滿頭問號。更離譜的是,面試官往往喜歡用這道題來判斷你對 Redis 架構底層原理是否真正吃透。
今天,我就用一個我親身經歷的“小故事”,帶你從懵逼到通透,一次把 Redis Cluster、DB 概念、鍵槽、遷移、為什麼只有 0 號庫 全説清楚。
準備好了嗎?故事開始啦。
面試前夜:我被“數據庫數量”絆倒了
上個月,我在準備一次社招面試。為了系統複習 Redis,我把筆記翻出來,看到一條不起眼的記錄:
“Redis 默認有 16 個數據庫(0-15)。”
我想:不就是 SELECT 2 切換數據庫嗎?太簡單了!
但就在我準備繼續往下看時,我突然腦袋一抽:
“等一下……Redis 集羣 模式下,還有多個 DB 嗎?
我們線上 RedisCluster 好像只有 0 號庫?
為什麼???”
並且我越想越怕:
“大廠面試會不會問這個???”
結果第二天,面試官真的問了……
面試現場:面試官一句話,我當場石化
面試官推推眼鏡,輕描淡寫地説:
“我們線上 RedisCluster 只用 0 號 DB,你知道為什麼嗎?”
我的腦子當場爆炸,所有知識像上線時的緩存擊穿一樣瞬間失效。
我試探性回答:
“因為……集羣模式不支持切換數據庫?”
面試官點點頭:
“那具體為什麼?底層原理你能説説嗎?”
我(內心):完了,這道題我知識點不夠,白給了。但我不能慫,於是我盡力從記憶裏拼湊答案…
可説實話,當下我答得很一般。回家後,我決定徹底把這個問題搞透。然後,就有了你現在看到的這篇文章。
要回答這個問題,我們必須從 Redis 朝我翻白眼的“根本原因”説起。
原因一:Redis Cluster 的數據分片依賴槽位(slot),與 DB 機制天然衝突
Redis Cluster 的核心設計哲學是:
全局只有一份槽位映射表(0~16383 共 16384 個)
每個 key 會根據 CRC16 算法計算 hash,然後映射到槽位:
slot = CRC16(key) % 16384
槽位對應節點 → 節點存儲數據 → 集羣分片實現
簡單直白:
槽位機制確保同一個 key 一定落在同一個節點上。
但是!但是!數據庫號(DB index)幹嘛用的?
同一個 Redis 實例內部,分隔不同的數據空間。
這就尷尬了:
如果 Redis Cluster 支持多 DB,那麼同一個 key 的數據會因為 DB 不同而分佈到不同節點,整個槽位映射會瞬間崩潰。
你不能讓:
- user:1 在 DB0 的 1000 號槽位
- user:1 在 DB2 的 9000 號槽位
這會讓 Redis Cluster 完全不知道:
“到底哪個才是正確的數據?到底該遷移哪個槽位?到底誰負責這個 key?”
槽位規則會被徹底破壞。因此作者(Antirez)説過一句非常明確的話:
Redis Cluster never supported multiple databases.Only DB 0 is allowed.
原因二:集羣節點之間需要遷移槽位,而多 DB 無法同步槽位元數據
Redis Cluster 會做槽位遷移,比如擴容縮容時:
migrate slot 5500 from node A → node B
如果支持多 DB,遷移邏輯會爆炸:
- 每個 DB 維護一份槽位映射?
- 每個 DB 都要遷移?
- 槽位在某個 DB 中不存在怎麼辦?
複雜度直線上升,並且毫無必要。於是 Redis 源碼中針對 cluster 直接寫死:
沒錯,就是寫死的。就是這麼絕情。
Redis 集羣為什麼乾脆“只保留一個 DB”?
這裏有兩個架構設計哲學:
1. 集羣場景強調“分佈式一致性”,不是“邏輯隔離”
數據庫號是一個“邏輯概念”,而 Redis Cluster 的目標是“分佈式可擴展性、容錯性、數據一致性”。
為了這三個目的,多 DB 反而是負擔。
2. 多 DB 的隔離性太弱,不符合大型系統需求
讓你想想:
- 多租户?
- 多項目?
- 數據隔離?
- 權限隔離?
- 安全管理?
你會用“Redis 的 0-15 DB”嗎?你敢嗎?不敢。
成熟項目都是:
- 多個 Redis 實例隔離
- 多個 Redis Cluster 隔離
DB 分區對大型系統來説是完全不夠用的。因此 Redis 作者很早就決定:
單機可以玩 DB
- 集羣模式一律只有 0 號庫
乾脆利落。
那 Java 項目要如何“模擬多數據庫”?
標準方法有三種:
方案一:使用不同的 key 前綴(最常用)
例如:
- prod:user:1001
- test:user:1001
- appA:config:*
- appB:session:*
Java 中可以通過 RedisTemplate 自動加前綴。
- 優點:簡單
- 缺點:需要管理 key 前綴格式
方案二:使用多個 Redis 實例
例如:
- 用户緩存 Redis
- 訂單緩存 Redis
- 會話 Session Redis
物理隔離,最安全。
方案三:使用多個 Redis Cluster(更大規模)
微服務架構常見設計:
- 用户域使用 user-redis-cluster
- 搜索域使用 search-redis-cluster
- 交易域使用 trade-redis-cluster
真正做到資源隔離、故障隔離、擴容獨立。
如果面試官問:Redis Cluster 能不能 SELECT 其他 DB?
你要這麼回答(必殺技):
“Redis Cluster 強制只使用 DB0,因為集羣的分片依賴 16384 槽位,而多 DB 會破壞槽位映射的一致性,並影響槽位遷移、節點擴容和數據分佈。因此 Redis 作者直接在源碼中禁用了多 DB,避免出現分佈式數據紊亂。”
面試官會覺得:
“這人懂架構,不是隻會用 API。”
同款面試題還能順手引申:
- Redis Cluster 的分片機制
- Redis 的擴容縮容
- 為什麼 key 必須能被 CRC16 hash
- 為什麼 hash tag({xxx})會出現
- 為什麼不要用 keys *
這些都是加分點。
我如何把這道題補強到“面試官滿意程度”?
我把這道題整理成了 標準面試答案模板(你可以直接記住):
標準面試總結(1 分鐘完美回答)
Redis Cluster 只支持 DB0,不支持 SELECT 切庫,原因是:
- Redis Cluster 基於槽位分片機制(16384 slots),所有 key 通過 CRC16 落到槽位,而槽位分片是整個集羣的數據一致性基礎。
- 多 DB 會破壞槽位模型,會導致相同 key 在不同 DB 中產生不同槽位,使節點無法判斷 key 的真正歸屬。
- 會導致槽位遷移複雜度暴增,遷移需要處理所有 DB,甚至槽位元數據會無法維護。
- 因此 Redis 在源碼裏直接寫死:Cluster 模式只允許 0 號數據庫。
- 多數據庫需求應通過 前綴隔離、多個實例、多個集羣 來實現,不推薦使用 Redis 的 DB 概念。
只要你能説到這些點,面試官基本會覺得你:
“不僅知道答案,還理解架構。”
故事尾聲:我在下一次面試實現“完美反殺”
一週後,我又去面了另外一家。面試官同樣問:
“講講 Redis 集羣為什麼只有 0 號數據庫?”
這次我胸有成竹,一套邏輯清晰的回答下來,面試官直接説:
“很好,你理解得很紮實。”
那一刻,我真的感覺:
技術的魅力不只是會用,而是——懂得為什麼。
這道題從前讓我害怕,現在卻成了我面試的加分項。希望你看完這篇文章後,也能從容面對。
END
當你理解一個知識背後的“設計哲學”時,它就不再是面試題,而是屬於你的武器。
今天的 Redis 故事,希望能幫你補齊這塊底層短板,在下一次面試裏穩穩拿分。
如果你覺得這篇文章對你有幫助,別忘了點個 在看 或 收藏,這樣我就知道要繼續寫更多類似的內容啦!
我是小米,一個喜歡分享技術的31歲程序員。如果你喜歡我的文章,歡迎關注我的微信公眾號“軟件求生”,獲取更多技術乾貨!