資料切成多個分片、散在多個節點之後,客戶端要讀寫某個 key,得先知道「它落在哪個節點」。這其實是服務發現 (service discovery) 的一個具體案例:有三種做法把請求送到對的節點,而它們共同的難題,是做決策的那一方如何得知「分片→節點」對應的變化。
🧠 Intuition
TIP
分片策略決定 key「屬於哪個分片」;請求路由要解的是下一步——「那個分片現在在哪個節點上」。三種做法差別只在「把知道對應關係的責任放在誰身上」:節點、路由層、還是客戶端。
- 三種做法:任意節點轉發(連上誰、誰不對就幫你轉)、獨立路由層(分片感知的負載平衡器)、客戶端自知分區(自己維護對應、直連)。
- 三者的核心問題其實同一個:做路由決策的那個元件,如何得知分片到節點的對應「變了」(再平衡、節點增減時)?
- 兩種傳播對應關係的路線:靠外部協調服務(如 ZooKeeper)維護權威對應並通知訂閱者;或靠節點間 gossip 去中心地互相傳播叢集狀態。
- 客戶端一開始要連的 IP,因為變動遠比分片對應慢,通常用 DNS 給就夠了。
⚖️ Tradeoffs
方式一:任意節點轉發 — 客戶端不必知道對應
- 客戶端可以連上任一節點;若該節點剛好持有目標分片就直接處理,否則把請求轉發到正確的節點。
- 好處:客戶端最單純,不需維護任何分片對應。
- 代價:多一跳轉發;且每個節點都得知道整個叢集的對應關係。
- 是 Cassandra、Riak 這類 gossip 系統的典型形態。
方式二:獨立路由層 — 分片感知的負載平衡
- 所有請求先經過一個路由層 (routing tier),由它判斷該交給哪個節點。
- 路由層本身不處理資料,只做「分片感知」的負載平衡與轉發。
- 對應關係集中在路由層一處維護,客戶端同樣不必知道分片細節。
- MongoDB 即以
mongos作為路由層(搭配 config server 保存對應)。
方式三:客戶端感知分區 — 少一跳,但客戶端變重
- 客戶端自行維護「分片→節點」對應,算出目標後直連正確節點。
- 好處:省掉中間轉發或路由層那一跳,延遲最低。
- 代價:對應關係變化時,每個客戶端都要及時更新,否則會連錯節點。
協調服務 ZooKeeper — 權威對應 + 主動通知
- 許多系統用獨立的協調服務 (coordination service) 如 ZooKeeper 管理叢集後設資料。
- 運作:每個節點向 ZooKeeper 註冊;ZooKeeper 持有分片到節點的權威對應;路由層或客戶端訂閱這份資訊。
- 當分片擁有者變更或節點增減時,ZooKeeper 通知所有訂閱者更新路由——對應變化因此能主動、一致地傳開。
- 採用者:LinkedIn Espresso(透過 Helix)、HBase、SolrCloud、Kafka。
去中心 gossip — 省掉外部依賴,換節點更複雜
- Cassandra、Riak 用八卦協定 (gossip protocol):節點之間互相傳播叢集狀態的變化,沒有外部協調服務。
- 請求可送到任意節點,由它轉發到正確的分片擁有者(即方式一)。
- 取捨:免去對 ZooKeeper 之類外部服務的依賴,但把對應關係傳播的複雜度搬進了資料庫節點本身。
平行查詢執行 (MPP) — 單鍵路由之外的另一種
- 前述都聚焦「單一 key」的讀寫路由,這是多數 NoSQL 分散式資料庫的存取層級。
- 大規模平行處理 (MPP) 的關聯式資料庫在分析型查詢上更複雜:查詢最佳化器會把一個複雜查詢拆成多個執行階段,分散到不同節點平行執行。
- 涉及大量資料掃描的查詢,從這種平行執行中獲益最大。
🔑 Takeaways
- 請求路由是服務發現的具體案例,要解的是「分片現在在哪個節點」,與分片策略是分開的兩件事。
- 三種做法差在責任放在誰身上:任意節點轉發、獨立路由層、客戶端自知分區——共同難題都是「如何得知對應變了」。
- 傳播對應關係有兩條路:ZooKeeper 等協調服務維護權威對應並主動通知訂閱者,或節點間 gossip 去中心互傳(免外部依賴、但節點更複雜)。
- 單鍵路由之外,MPP 資料庫會把複雜查詢拆成多階段、跨節點平行執行,適合大量掃描的分析查詢。
No notes yet — jot your takeaways or Q&A here.