大家好,我是小米,一個 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 集羣為什麼只能用 0 號數據庫?_數據庫

沒錯,就是寫死的。就是這麼絕情。

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 切庫,原因是:

  1. Redis Cluster 基於槽位分片機制(16384 slots),所有 key 通過 CRC16 落到槽位,而槽位分片是整個集羣的數據一致性基礎。
  2. 多 DB 會破壞槽位模型,會導致相同 key 在不同 DB 中產生不同槽位,使節點無法判斷 key 的真正歸屬。
  3. 會導致槽位遷移複雜度暴增,遷移需要處理所有 DB,甚至槽位元數據會無法維護。
  4. 因此 Redis 在源碼裏直接寫死:Cluster 模式只允許 0 號數據庫
  5. 多數據庫需求應通過 前綴隔離、多個實例、多個集羣 來實現,不推薦使用 Redis 的 DB 概念。

只要你能説到這些點,面試官基本會覺得你:

“不僅知道答案,還理解架構。”

故事尾聲:我在下一次面試實現“完美反殺”

一週後,我又去面了另外一家。面試官同樣問:

“講講 Redis 集羣為什麼只有 0 號數據庫?”

這次我胸有成竹,一套邏輯清晰的回答下來,面試官直接説:

“很好,你理解得很紮實。”

那一刻,我真的感覺:

技術的魅力不只是會用,而是——懂得為什麼。

這道題從前讓我害怕,現在卻成了我面試的加分項。希望你看完這篇文章後,也能從容面對。

END

當你理解一個知識背後的“設計哲學”時,它就不再是面試題,而是屬於你的武器。

今天的 Redis 故事,希望能幫你補齊這塊底層短板,在下一次面試裏穩穩拿分。

如果你覺得這篇文章對你有幫助,別忘了點個 在看收藏,這樣我就知道要繼續寫更多類似的內容啦!

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