redis集群實現(二)集群新增節點

2021-08-07 14:05:04 字數 4071 閱讀 5881

在redis-3.0.0裡,集群新增節點是通過客戶端執行cluster meet命令來實現的,命令格式是cluster meet ,如果客戶端向a節點傳送這條命令,ip和port分別是b節點的ip和port,就會把ip:port的機器新增進入執行命令的節點所在的集群裡。

具體的流程如下:

1.首先客戶端向a節點傳送cluster meet 命令。

2.a節點在本地為b節點建立對應的資料結構,然後向b節點傳送meet命令。

3.b節點在本地為a節點建立相應的資料結構,並向a節點傳送pong訊息,表示收到a節點的訊息。

4.a節點收到pong以後,向b節點返回ping訊息。

5.a節點通過gossip協議向集群中的其他節點傳播,一段時間以後,集群中所有的節點都會知道b。

如圖:

理解了原理了以後,我們就來看一看redis-3.0.0裡對於cluster meet命令以及後續的過程的**實現,以便於更加深入的理解redis。

redis的meet命令的定義是clustercommand函式,我們看看clustercommand函式對於meet的實現。

[cpp]view plain

copy

void

clustercommand(redisclient *c)       

//匹配命令,如果是meet就進入下邊的**

if(!strcasecmp(c->argv[1]->ptr,

"meet"

) && c->argc == 4)       

// 嘗試與給定位址的節點進行連線

if(clusterstarthandshake(c->argv[2]->ptr,port) == 0 &&   

errno == einval)  

else

}  ……………………………………………….  

主要的處理邏輯函式是clusterstarthandshake,這個函式向ip:port進行握手,成功時返回1,我們看看clusterstarthandshake函式的**實現吧

[cpp]view plain

copy

intclusterstarthandshake(

char

*ip, 

intport)  else

if(inet_pton(af_inet6,ip,  

&(((struct

sockaddr_in6 *)&sa)->sin6_addr)))  

else

// port 合法性檢查

if(port <= 0 || port > (65535-redis_cluster_port_incr))   

if(sa.ss_family == af_inet)  

inet_ntop(af_inet,  

(void

*)&(((

struct

sockaddr_in *)&sa)->sin_addr),  

norm_ip,redis_ip_str_len);  

else

inet_ntop(af_inet6,  

(void

*)&(((

struct

sockaddr_in6 *)&sa)->sin6_addr),  

norm_ip,redis_ip_str_len);  

// 檢查節點是否已經傳送握手請求,如果是的話,那麼直接返回,防止出現重複握手

if(clusterhandshakeinprogress(norm_ip,port))   

// 對給定位址的節點設定乙個隨機名字

// 當 handshake 完成時,當前節點會取得給定位址節點的真正名字

// 建立乙個集群節點,flag設定為meet,發出meet命令

n = createclusternode(null,redis_node_handshake|redis_node_meet);  

memcpy(n->ip,norm_ip,sizeof

(n->ip));  

n->port = port;  

// 將節點新增到集群當中

clusteraddnode(n);  

return

1;  

}  

我們繼續看createclusternode函式和clusteraddnode函式。

[cpp]view plain

copy

createclusternode函式建立了乙個clusternode結構體,並且設定狀態為handshake和meet  

/* * 函式會返回乙個被建立的節點,但是並沒有把它加入到當前節點的雜湊表裡

*/clusternode *createclusternode(char

*nodename, 

intflags)   

然後是clusteraddnode函式,這個函式把乙個剛剛建立好的節點加入到當前節點雜湊表裡邊,**非常簡單。

[cpp]view plain

copy

// 將給定 node 新增到節點表裡面

intclusteraddnode(clusternode *node)   

看到這裡,你可能會問,怎麼沒有看到傳送meet資訊的**?其實meet資訊是在servercron函式裡邊傳送的,servercron函式是乙個週期性執行的函式,一般是每秒呼叫10次,就是每100ms呼叫一次。servercron函式的功能是清除一些過期的key-value和統計資訊,複製等一些操作。在servercron函式裡有以下**:

[cpp]view plain

copy

// 如果伺服器執行在集群模式下,那麼執行集群操作

run_with_period(100)   

這裡就是每100ms會執行clustercron函式,clustercron函式執行集群的定期檢查工作,在clustercron函式裡執行了傳送meet訊息的工作,具體實現如下:

[cpp]view plain

copy

void

clustercron(

void

)   

自此,我們就把meet訊息傳送出去了~~然後,我們就看看另乙個節點是怎麼接收到meet訊息的吧。

又回到clustercron函式,在clustercron函式裡,為沒有建立連線的節點結構體設定對應的訊息處理函式,**如下

[cpp]view plain

copy

if(node->link == null)   

/* get info from the gossip section */

// 分析並取出訊息中的 gossip 節點資訊

clusterprocessgossipsection(hdr,link);  

/* anyway reply with a pong */

// 向目標節點返回乙個 pong

clustersendping(link,clustermsg_type_pong);  

}  ………………………………………..  

節點傳送了pong,我們就該接收pong,同樣是在clusterprocesspacket函式,接受pong訊息的處理**如下:

[cpp]view plain

copy

if(link->node && type == clustermsg_type_pong)  else

if(nodefailed(link->node))   

}  ………………………………………  

接收到pong訊息以後,撤銷了節點的fail狀態,以後就會在servercron函式裡週期性向新加入節點傳送ping,然後新加入的節點返回pong,這方面的**會在後續的專題寫,自此雙方的資訊就都了解清楚了。

ElasticSearch之二 集群

首先看下elasticsearch es 的架構 術語解釋 es的分布式操作大多是自動完成的 1 跨節點平衡集群中各節點的索引與搜尋負載 2 自動複製索引資料以提供冗餘副本,防止硬體錯誤導致資料丟失 3 自動在節點之間路由,以幫助找到檢索的資料 4 無縫擴充套件或者恢復集群 node 節點 是es執...

elasticsearch技術總結(二) 集群管理

所謂集群管理是指集群搭建好後的日常維護和管理。一 集群健康 集群狀態分為三種 green 所有主分片以及副分片都可用 yellow 部分副本不可用 red 丟失分片 其中集群狀態為 green 和 yellow 集群正常,資料完整 狀態為red部分資料丟失,分配到缺失分片的操作會有異常 集群狀態以及...

storm 二 集群提交拓撲

準備工作 將開發好的jar包上傳到伺服器nimbus節點上,如package目錄下 啟動storm集群 storm jar wordcountbyandy.jar com.andy.learning.storm helloworld.topology testtask1解釋下這條命令中的各個引數 執...