redis叢集資料結構
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2csITQU10dNR1TyR2MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLzEDN0MDNzIjMxMDOwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
clusterNode結構儲存了一個節點的狀态,比如節點的建立時間,名稱。負責處理哪些槽(槽是redis叢集的一個最重要的一個概念,後邊會講到)
clusterLink結構儲存了連接配接節點所需要的資訊,比如套接字描述符,輸入緩存區和輸出緩沖區,主要是用于連接配接其他節點。
每個節點都儲存着一個clusterState結構。這個結構記錄了在目前結點的視角下,叢集的狀态,叢集所包含的節點等資訊
槽指派
redis 叢集通過分片的方式儲存資料庫中的鍵值對:叢集的整個資料庫被分為16384個槽(slot),資料庫中每個鍵都屬于這16384個槽的其中一個,叢集中的每個節點負責0個或者最多16384個槽。
怎麼計算鍵key屬于哪個槽?
節點使用以下方法計算給定的鍵key屬于哪個槽:CRC16(key) & 16383 CRC16(key) 計算鍵key的CRC16校驗和。& 16383 計算出一個0至16383之間的整數作為key的槽号。
節點收到一些指令的時候怎麼高效判斷這個key是否應該由自己處理或者該有其他節點去處理?
首先叢集中每個節點會處理部分槽,所有節點處理完一共16384個槽。節點之間會互相傳播槽指派資訊。節點收到其他節點發送的槽指派資訊之後,會在本節點的clusterState結構的slots數組記錄每個槽由哪個節點負責處理。
假設key 經過計算有槽5000負責,那麼如下圖,節點會以5000為下标取出數組的值,數組的值其實就對應了一個clusterNode結構,取出的值為node2,那麼key會有節點node2代表的節點處理。當然如果通過下标取出的clusterNode為null,表示該槽尚未配置設定。
假設本節點就是node2,那麼本節點會直接執行指令;假設本節點不是node2,那麼節點會根據node2所代表節點的ip 和端口号,向用戶端傳回MOVED錯誤,指引用戶端轉向處理該槽的節點。可以看出找出key 對應的槽有哪個節點處理的複雜度為O(1),是相當高效的。
重新分片
redis叢集的重新分片操作可以将任意數量已經指派給某個節點(源節點)的槽改為指派個另一個節點(目标節點),在重新分片的過程中,叢集不需要下線,并且源節點和目标節點都可以繼續處理指令請求。
當用戶端向一個客戶算發送指令的時候,而對應的槽正被遷移,那麼如果redis在目前節點找到對應的key 就直接執行指令請求,如果沒有找到就會傳回用戶端ASK錯誤(使用者不會感覺)指引用戶端通路目标節點。