← 回首頁

分散式快取(Consistent Hashing 雜湊環 + KV 前綴快取)

想像一家連鎖餐廳把客人分到不同分店:每開一家新店就叫所有老客人重排隊換店,實在太折騰。分散式系統 把資料散在很多台機器上也有同樣煩惱——加減機器時,最好只搬一小部分、別讓全部重來。一致性雜湊 (Consistent Hashing)就是把機器和資料排在一個「圓環」上,加機器時只驚動旁邊少少幾筆;KV 前綴 快取(prefix caching)則是把 AI 對話裡一再重複的開頭存起來重用、省下重算。下面你會看到這兩招各自 怎麼運作。

分散式系統把資料/請求分散到多台機器時,總要面對「這個鍵該去哪台?」的定址問題——一致性雜湊 (Consistent Hashing)用一個環狀雜湊空間解決「節點增減時盡量少搬資料」的難題;LLM 推理服務則有 另一種快取問題:多筆請求常共享相同的提示詞前綴,如何辨識並復用已算過的部分以省下重算成本, 正是 KV 前綴快取(prefix caching)要處理的事。兩者手法不同,但都是「雜湊定址 + 容量有限的取捨」 在分散式/推理場景下的具體應用,本頁把它們放在同一頁,逐步展示各自的核心機制。

為什麼 AI 時代重要

分散式快取/儲存分片是向量資料庫與快取叢集的標準做法:Memcached client-side sharding、 DynamoDB/Cassandra 的分區策略都採一致性雜湊,讓叢集擴縮容時只需搬移少數鍵,避免大規模資料 重新分佈造成的雪崩式快取失效(cache stampede)。另一方面,LLM 推理服務(vLLM、SGLang 等)的 KV cache 前綴復用是省算力的關鍵最佳化之一——多筆請求常共享相同的 system prompt 或對話前綴, 快取已算過的前綴 KV 狀態可直接復用,省下重算前綴部分的算力,這正是本頁第 2 節示範的核心概念。

它是雜湊表與 LRU 的分散式延伸

一致性雜湊本質上是把雜湊表「查表找桶」的定址問題,從單機固定桶陣列延伸到分散式節點集合:桶 索引查找換成雜湊環上的順時針查找,虛擬節點則是緩解負載不均的手法,詳見 雜湊 Hash Table/Bloom Filter。KV 前綴快取則是把 LRU Cache「容量有限、淘汰最久未用」的邏輯套用到推理場景:命中判準從「鍵完全相等」改為「最長 前綴命中」,其餘容量限制與逐出策略與經典 LRU 相同,詳見 鏈結串列與 LRU Cache

1. Consistent Hashing(一致性雜湊:雜湊環 + 虛擬節點 + 搬移對照)

建置雜湊環:每個實體節點放置多個虛擬節點(vnode),依 hash(vnode 名稱) 算出 0..359 度的環座標, 依角度排序插入環。查找歸屬:鍵的環座標同樣以 hash(鍵) 算出,沿順時針方向找「第一個角度 ≥ 鍵座標」 的 vnode 即為其歸屬(若鍵座標大於環上所有角度,折返取角度最小者,因為環是首尾相接的圓)。 加入新節點時只需在環上插入該節點的 vnode,只有落在新 vnode 與其順時針前一個 vnode 之間的鍵才會 改變歸屬——這就是一致性雜湊「節點增減只搬少數鍵」的關鍵,本頁同幀對照傳統取模雜湊(hash % N) 的搬移數,兩者差距正是教學核心。

固定資料:初始 3 實體節點 A/B/C,各 2 個 vnode(A-0/A-5、B-2/B-7、C-4/C-9);鍵 k1..k8; 加入節點 D 之 2 個 vnode(D-39/D-37)。教學雜湊 h(s) = Σ字元碼×31^i mod 360,環座標 0..359 度(時鐘刻度,僅供教學直觀,非生產雜湊函式)。
累計順時針查找次數(lookups):0 階段:place-vnode
外環節點 = 虛擬節點(vnode,標籤如 A-0);內環節點 = 鍵(標籤如 k1);有向邊 = 「鍵 → 其歸屬 vnode」。橘色(current)=當下處理/查找到的 vnode;紅色外框(本頁自訂)=重算後判定「已搬移」 的鍵,或新放置的 vnode;淺色走訪標記=正在處理但尚未判定搬移的鍵;綠色(finalized)=終幀標示 之一致性雜湊搬移鍵集合。
虛擬節點的作用:只放 1 個實體節點對 1 個環座標,容易讓少數節點各自負責過長的環弧段 (負載不均);每個實體節點放多個 vnode,等於把它的負責範圍拆成多段、分散在環上不同位置, 統計上更容易讓各節點負責的鍵數趨於平均。
順時針規則:鍵一律沿順時針方向找「第一個角度 ≥ 自己座標」的 vnode 為歸屬,環是首尾 相接的圓,超過環上最大角度會折返取角度最小的 vnode(本頁 ceilingVnode 以排序陣列 + 二分搜尋 實作,對照 Java TreeMap.ceilingEntry/firstEntry)。
教學雜湊非生產:h(s) = Σ字元碼×31^i mod 360 只是讓環座標落在直觀的「時鐘刻度」 0..359 度之教學設計,不具生產雜湊函式所需的雪崩效應與抗碰撞性,正式系統應改用 MD5/MurmurHash/SHA-1 等分佈更均勻、抗碰撞的雜湊函式再取模至環空間。
360 度教學空間:本頁環空間固定為 360 度,純粹取「時鐘刻度」的直覺對應,與實際部署 的雜湊環大小(生產系統常見 2^32 或更大)無關,教學規模下才看得出「歸屬邊隨環座標分佈」的 視覺直觀,看不出真正生產環境的雜湊分佈密度。

歸屬表(assignments,逐鍵目前已知之歸屬)

hash歸屬 vnode歸屬節點已搬移(加 D 後)

搬移對照表(一致性雜湊 vs 取模雜湊,3→4 節點)

雜湊方式搬移鍵數搬移鍵集合

已執行操作紀錄(opLog)

(空)

2. KV 前綴快取(最長前綴命中 + LRU 逐出 + 省算對照)

每筆請求先做一次唯讀掃描:對快取內每筆既有 entry,若為本次請求 token 序列的前綴,取「最長」者為 命中(hitLength = 該 entry 長度);此掃描不影響任何 entry 的 LRU 新鮮度。不論命中與否,本次請求 的完整 token 序列都會被當作一筆新 entry 寫入快取——若該完整序列已存在則僅移至最新(不重複計數), 否則新增,超過容量則逐出「新鮮度最舊」的 entry。累加每筆請求的 hitLength 即為 tokensSaved,代表 「有快取」相對「無快取每次全部重算」省下的 token 計算量。

固定資料:容量 3;5 筆共享前綴之請求 [系統,你,好] / [系統,你,好,嗎] / [系統,天,氣] / [系統,天,氣,嗎] / [系統,你,好]。快取槽以 3 列(容量)× 4 欄(最長請求 token 數)呈現, 較短序列以空白補齊。
已完整處理(寫入)之請求數(steps):0 階段:init
列 = 快取槽(容量 3,index 0 = 最舊);欄 = token 位置(最長請求 4 token,較短序列右側留空)。 藍色外框(active)標示本步驟命中的既有 entry 的 token 欄,或本步驟新寫入的 entry 佔用的欄; 粉紅(pivot)標示命中 entry 的最後一個 token(即命中長度所在位置)。
KV 為概念示意,非真實 attention cache 結構:本頁僅以 token 字串序列模擬「快取 條目」,不模擬真實推理引擎的 attention KV 張量結構(實際上是每層、每個 attention head 各自 一份 key/value 張量),呼應 vLLM、SGLang 等推理框架之 prefix caching/RadixAttention 概念, 但本頁看不出真正的記憶體佈局與張量運算。
命中唯讀,不刷新 LRU:前綴比對是唯讀掃描,即使某 entry 被判定為本次命中,也不會 把它移到「最新」——只有當一筆請求的完整 token 序列被寫入快取時,才會影響 LRU 新鮮度(新增或 移至最新)。
前綴復用省算:命中長度即為本次請求省下重算的 token 數,下方「省算對照」逐步累加 savedTokens,對照「無快取」情境下每次都要全部重算的 token 總量。

目前快取內容(cacheEntries,舊→新)

(空)

逐請求記錄(requests:命中長度/逐出)

請求tokens命中 entry(長度)逐出

省算對照(savedTokens:有快取 vs 無快取重算 token 數)

(尚無資料)

已執行操作紀錄(opLog)

(空)