在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解釋下這條命令中的各個引數 執...