1. 程式人生 > 其它 >《Redis設計與實現》讀書筆記(三十一) ——Redis叢集訊息型別

《Redis設計與實現》讀書筆記(三十一) ——Redis叢集訊息型別

《Redis設計與實現》讀書筆記(三十一) ——Redis叢集訊息型別

(原創內容,轉載請註明來源,謝謝)

1、傳送訊息型別

叢集中節點通過傳送與接收訊息進行通訊。

傳送訊息的節點稱為訊息傳送者,接收訊息節點稱為接收者。訊息傳送型別如下:

1)meet

當客戶端傳送clustermeet給節點,節點會發送meet訊息給接收者,請求接收者加入到傳送者當前的叢集中。

2)ping

每個節點每秒,預設會隨機從當前已知節點列表,挑選5個節點,並從中挑選最久未傳送過ping訊息的節點,對其傳送ping,檢測其是否線上。

另外,如果某個節點最後一次回覆pong的時間,距離當前時間,已經超過redis配置檔案中cluster-node-timeout設定的秒數的一半,則也會對該節點發送ping,防止多次沒有隨機到該節點,導致對該節點的狀態更新過慢。

3)pong

當節點收到meet或者ping,為了告知傳送者收到訊息,會回覆pong。

另外,完成一次故障轉移後,新的主節點會給向叢集廣播pong。

4)fail

當節點認為某個節點下線,會向叢集廣播關於該節點的fail狀態,其他節點接收到後,都會將該節點狀態置為下線。

5)publish

當節點收到publish命令,會執行該命令,並向叢集傳送publish,其他節點收到後也會執行該命令。

2、訊息頭

所有訊息都由訊息頭包裹,訊息頭可以認為是訊息的一部分。訊息頭由cluster.h/clusterMsg結構記錄,如下:

         structclusterMsg{
         uint32_t totlen;//訊息總長度,包括訊息頭長度和正文長度
         uint16_t type;//訊息型別
         uint16_t count;//訊息正文包含節點資訊數量,只有在meet、ping、pong這三種涉及到gossip協議的型別使用
         uint64_t currentEpoch;//傳送者的配置紀元
uint64_t configEpoch;//該節點是主節點時,是傳送者的配置紀元;是從節點時,是對應正在複製的主節點的配置紀元
         char sender[REDIS_CLUSTER_NAMELEN];//傳送者名字(ID)
         unsigned char myslots[REDIS_CLUSTER_SLOTS/8];//傳送者目前的槽資訊
         char slaveof[REDIS_CLUSTER_NAMELEN];//主節點時記錄的是40位長的都是0的字串,從節點時記錄的是複製的主節點的名字
         uint16_t port;//傳送者埠號
         uint16_t flag;//傳送者標識值
         unsigned char state;//傳送者所處的叢集狀態
         union clusterMsgData data;//訊息的正文
}clusterMsg;

訊息的正文是一個聯合體,共有三種類型結構體,包括ping、fail、publish,其中pong、meet型別都和ping一樣。

3、meet、ping、pong

這三個的型別一樣,都是記錄在聯合體clusterMsgData中的結構體。因為這三種訊息有相同的正文,節點是通過訊息頭的type判斷是這三種的哪一種。

這三種訊息的型別是clusterMsgDataPublish,這是一個結構體,記錄節點名字、最後給該節點發送ping的時間戳、最後收到節點pong的時間戳、節點ip、埠號、標識等。

當節點接收到資訊時,如果不認識裡面的節點,則會與節點進行握手,如果認識則更新對應的資訊。

4、fail

由於使用gossip協議會有延遲,fail是用來表示該節點下線,需要儘快傳達,因此不用gossip協議,而是立即讓叢集中的全部節點知情。其正文就是下線節點的名字。

5、publish

客戶端向叢集傳送publish<channel> <message>,接收的頻道不僅會向頻道channel傳送message,還會向叢集廣播publish,其他節點也會執行該命令。

因此,向某個節點發送publish,會導致所有節點都執行該命令。

具體流程如下:

publish用結構體clusterMsgDataPublish記錄,內容是包括頻道長度,訊息長度,以及具體內容。

其中,bulk_data的前channel_len位元組,記錄channel引數;剩餘位元組記錄message引數。

例如,傳送publish“news.it” “hello” 如下:

其實也可以直接向叢集廣播publish命令,但是由於其不符合redis設計的各節點通過訊息傳送和接收來傳播訊息的做法,因此採用對某一節點進行訊息傳送。

——written by linhxx 2017.09.18