我在《那些年用過的Redis集羣架構(含面試解析)》一文裏提到過,如今redis集羣架構,redis cluster用的會比較多。
以下圖所示
對於客戶端請求的key,根據公式HASH_SLOT=CRC16(key) mod 16384
,計算出映射到哪一個分片上,而後Redis會去相應的節點進行操做!html
那你們思考過,爲何有16384個槽麼?
ps
:CRC16
算法產生的hash值有16bit,該算法能夠產生2^16-=65536個值。換句話說,值是分佈在0~65535之間。那做者在作mod
運算的時候,爲何不mod
65536,而選擇mod
16384?node
其實我當初第一次思考這個問題的時候,我內心是這麼想的,做者應該是以爲16384就夠了,而後我就開始查這方面資料。git
很幸運的是,這個問題,做者是給出了回答的!
地址以下:
https://github.com/antirez/redis/issues/2576
github
做者原版回答以下:
The reason is:面試
So 16k was in the right range to ensure enough slots per master with a max of 1000 maters, but a small enough number to propagate the slot configuration as a raw bitmap easily. Note that in small clusters the bitmap would be hard to compress because when N is small the bitmap would have slots/N bits set that is a large percentage of bits set.redis
所以,能看懂上面那段話的讀者。這篇文章不用看了,由於做者講的很清楚了。本文只是對上面那段話作一些解釋而已。算法
咱們回憶一下Redis Cluster
的工做原理!
這裏要先將節點握手講清楚。咱們讓兩個redis節點之間進行通訊的時候,須要在客戶端執行下面一個命令數組
127.0.0.1:7000>cluster meet 127.0.0.1:7001
以下圖所示
網絡
意思很簡單,讓7000節點和7001節點知道彼此存在!
在握手成功後,連個節點之間會按期發送ping/pong消息,交換數據信息,以下圖所示。
架構
在這裏,咱們須要關注三個重點。
到底在交換什麼數據信息?
交換的數據信息,由消息體和消息頭組成。
消息體無外乎是一些節點標識啊,IP啊,端口號啊,發送時間啊。這與本文關係不是太大,我不細說。
咱們來看消息頭,結構以下
注意看紅框的內容,type表示消息類型。
另外,消息頭裏面有個myslots的char數組,長度爲16383/8,這實際上是一個bitmap,每個位表明一個槽,若是該位爲1,表示這個槽是屬於這個節點的。
到底數據信息究竟多大?
在消息頭中,最佔空間的是myslots[CLUSTER_SLOTS/8]
。這塊的大小是:
16384÷8÷1024=2kb
那在消息體中,會攜帶必定數量的其餘節點信息用於交換。
那這個其餘節點的信息,究竟是幾個節點的信息呢?
約爲集羣總節點數量的1/10,至少攜帶3個節點的信息。
這裏的重點是:節點數量越多,消息體內容越大。
消息體大小是10個節點的狀態信息約1kb。
那按期的頻率是什麼樣的?
redis集羣內節點,每秒都在發ping消息。規律以下
所以,每秒單節點發出ping消息數量爲
數量=1+10*num(node.pong_received>cluster_node_timeout/2)
那大體帶寬損耗以下所示,圖片來自《Redis運維與實現》
講完基礎知識之後,咱們能夠來看做者的回答了。
(1)若是槽位爲65536,發送心跳信息的消息頭達8k,發送的心跳包過於龐大。
如上所述,在消息頭中,最佔空間的是myslots[CLUSTER_SLOTS/8]
。
當槽位爲65536時,這塊的大小是:
65536÷8÷1024=8kb
由於每秒鐘,redis節點須要發送必定數量的ping消息做爲心跳包,若是槽位爲65536,這個ping消息的消息頭太大了,浪費帶寬。
(2)redis的集羣主節點數量基本不可能超過1000個。
如上所述,集羣節點越多,心跳包的消息體內攜帶的數據越多。若是節點過1000個,也會致使網絡擁堵。所以redis做者,不建議redis cluster節點數量超過1000個。
那麼,對於節點數在1000之內的redis cluster集羣,16384個槽位夠用了。沒有必要拓展到65536個。
(3)槽位越小,節點少的狀況下,壓縮比高
Redis主節點的配置信息中,它所負責的哈希槽是經過一張bitmap的形式來保存的,在傳輸過程當中,會對bitmap進行壓縮,可是若是bitmap的填充率slots / N很高的話(N表示節點數),bitmap的壓縮率就很低。
若是節點數不多,而哈希槽數量不少的話,bitmap的壓縮率就很低。
ps
:文件壓縮率指的是,文件壓縮先後的大小比。
綜上所述,做者決定取16384個槽,很少很多,剛恰好!
但願你們有所收穫!