redis cluster 有固定的 16384 個 hash slot把夸,對每個 key 計算 CRC16 值恋日,然后對 16384 取模,可以獲取 key 對應(yīng)的 hash slot岂膳。
HASH_SLOT = CRC16(key) mod 16384
為什么選擇mod 16384呢磅网?
In our tests CRC16 behaved remarkably well in distributing different kinds of keys evenly across the 16384 slots
官網(wǎng)說:在測試中發(fā)現(xiàn),使用CRC16算法計算出來的key可以在16384個槽中均勻分布簸喂。
用一個例子看看hash slot是怎么實現(xiàn)的:
我們假設(shè)現(xiàn)在有3個節(jié)點已經(jīng)組成了集群燎潮,分別是:A, B, C 三個節(jié)點,它們可以是一臺機器上的三個端口确封,也可以是三臺不同的服務(wù)器再菊。那么颜曾,采用hash slot的方式來分配16384個slot 的話,它們?nèi)齻€節(jié)點分別承擔(dān)的slot 區(qū)間是:
- 節(jié)點A覆蓋0-5460;
- 節(jié)點B覆蓋5461-10922;
- 節(jié)點C覆蓋10923-16383.
節(jié)點上使用bitmap記錄各自的hash slot绿语。
那么候址,現(xiàn)在我想設(shè)置一個key, 比如叫my_name
:
set my_name *****
hash slot:CRC16('my_name')%16384 = 2412
。 那么就會把這個key 的存儲分配到 A 上了岗仑。
我想獲取my_name
get my_name
會出現(xiàn)兩種情況:
- client剛好直接訪問到Node A,Node A查詢自己的hash slot表稳其,發(fā)現(xiàn)key->my_name在自己節(jié)點中,接著處理命令既鞠,獲取my_name的值返回客戶端盖文。
- client訪問到Node B或者Node C,發(fā)現(xiàn)key->my_name在Node A中五续,返回MOVED error。然后client重定向到該節(jié)點
GET my_name
-MOVED 2412 127.0.0.1:6381
ps: client也可以緩存各節(jié)點的hash slot map
新增一個Node D:
從各個節(jié)點的前面各拿取一部分slot到Node D上
- 節(jié)點A覆蓋1365-5460
- 節(jié)點B覆蓋6827-10922
- 節(jié)點C覆蓋12288-16383
- 節(jié)點D覆蓋0-1364,5461-6826,10923-12287
同樣刪除一個節(jié)點也是類似凶伙,移動完成后就可以刪除這個節(jié)點了函荣。