摘要:Gossip协议是Cassandra维护各节点状态的一个重要组件,下面我们以Gossip协议三次握手为线索逐步分析Gossip协议源码。

Gossip协议是Cassandra维护各节点状态的一个重要组件,下面我们以Gossip协议三次握手为线索逐步分析Gossip协议源码。

Gossip协议通过判断节点的generationversion 来确认节点状态信息新旧,如果节点重启,则generation加一,version每次从零开始计算。所以 generation是大版本号,version为小版本号,理解这个概念对后面的握手逻辑有很大帮助。

Gossip协议最重要的一个属性是endpointStateMap ,这个map以address为key,以EndpointState为value维护节点自身状态信息。EndopointState 包含了节点 net_version,host_id,rpc_address,release_version,dc,rack,load,status,tokens 信息。总体来说,所有节点维护的endpointStateMap应该是一致的,如果出现不一致信息或者新增,替换,删除节点 ,这中间的状态维护就要靠Gossip来实现了。

另外一个重要属性subscribers ,当节点状态变更时候,gossip 会通知各个subscribers。

Gossip启动时候,会每隔一秒会在集群中随机选择一个节点发送一条GossipDigestSyn消息,开始和其他节点的通信,如下图:

接下来我们根据上面的了流程图一步步分析gossip代码,GossipDigestSyn 消息是在GossipTask构造的。

1  // syn消息包含 集群名字,分区器,和gDigests消息
2 GossipDigestSyn digestSynMessage = new GossipDigestSyn(DatabaseDescriptor.getClusterName(),DatabaseDescriptor.getPartitionerName(),gDigests);
3
4 MessageOut<GossipDigestSyn> message = new MessageOut<GossipDigestSyn>(MessagingService.Verb.GOSSIP_DIGEST_SYN,digestSynMessage,GossipDigestSyn.serializer);

GossipDigestSyn 消息的主要部分在gDigests里面,gDigests是通过方法Gossiper.instance.makeRandomGossipDigest(gDigests) 生成的。

private  void  makeRandomGossipDigest(List<GossipDigest> gDigests)
02 {
03 EndpointState epState;
04 int generation = 0 ;
05 int maxVersion = 0 ;
06
07 // local epstate will be part of endpointStateMap
08 //当前节点维护的节点列表
09 List<InetAddress> endpoints = new ArrayList<InetAddress>(endpointStateMap.keySet());
10 //乱序处理
11 Collections.shuffle(endpoints, random);
12 for (InetAddress endpoint : endpoints)
13 {
14 epState = endpointStateMap.get(endpoint);
15 if (epState != null )
16 {
17 //获取generation版本号
18 generation = epState.getHeartBeatState().getGeneration();
19 //EndpointState包含了tokens,hostid,status,load等信息,所以冒泡排序获取其中最大的maxVersion
20 maxVersion = getMaxEndpointStateVersion(epState);
21 }
22 gDigests.add( new GossipDigest(endpoint, generation, maxVersion));
23 }
24
25 if (logger.isTraceEnabled())
26 {
27 StringBuilder sb = new StringBuilder();
28 for (GossipDigest gDigest : gDigests)
29 {
30 sb.append(gDigest);
31 sb.append( " " );
32 }
33 logger.trace( "Gossip Digests are : {}" , sb);
34 }
35 }

A节点发出GossipDigestSyn后,B节点会通过GossipDigestSynVerbHandler 来处理GossipDigestSyn 消息,具体处理逻辑在Gossiper.instance.examineGossiper中,

上面方法对比版本号以后,主要处理逻辑在senall方法和requestAll方法,继续跟进:

1  private  void  requestAll(GossipDigest gDigest, List<GossipDigest> deltaGossipDigestList,  int  remoteGeneration)
2 {
3 /* We are here since we have no data for this endpoint locally so request everthing. */
4 //生成一个Digest,等待对方节点发送消息
5 deltaGossipDigestList.add( new GossipDigest(gDigest.getEndpoint(), remoteGeneration, 0 ));
6 if (logger.isTraceEnabled())
7 logger.trace( "requestAll for {}" , gDigest.getEndpoint());
8 }
1 private void sendAll(GossipDigest gDigest, Map<InetAddress, EndpointState> deltaEpStateMap, int maxRemoteVersion)
2 {
3 EndpointState localEpStatePtr = getStateForVersionBiggerThan(gDigest.getEndpoint(), maxRemoteVersion);
4 if (localEpStatePtr != null )
5 //将endpintState信息通过ack 消息发送给对方
6 deltaEpStateMap.put(gDigest.getEndpoint(), localEpStatePtr);
7 }

到这里我们发现向对方节点发送的ack消息已经构造完成了,包含了deltaGossipDigestList(对方节点信息最新,我们需要对方节点给我们发endpointState) 和 deltaEpStateMap(当前节点新,我们发送给对方节点) 。

Gossip 通过GossipDigestAckVerbHandler 处理ack消息,主要逻辑有两块:

1.如果deltaEpStateMap有数据,则说明需要更新本地applicationState,执行Gossiper.instance.applyStateLocally方法

2.如果deltaGossipDigestList 有数据,则说明对方节点需要更新,构造EndpointState,并发送ack2消息给对方

GossipDigestAck2VerbHandler 用来处理 ack2消息,主要逻辑也在Gossiper.instance.applyStateLocally中,我们看一下Gossiper.instance.applyStateLocally的逻辑:

到这里Gossip 三次握手的全过程就分析完了(由于平台字数限制,部分代码以图片形式展示,可点击放大查看哦)。

点击关注,第一时间了解华为云新鲜技术~

Cassandra Gossip协议的二三事儿的更多相关文章

  1. Dynamo涉及的算法和协议——p2p架构,一致性hash容错+gossip协议获取集群状态+向量时钟同步数据

    转自:http://www.letiantian.me/2014-06-16-dynamo-algorithm-protocol/ Dynamo是Amazon的一个分布式的键值系统,P2P架构,没有主 ...

  2. Cassandra1.2文档学习(2)——节点间通信协议之gossip协议

    参考文档:http://www.datastax.com/documentation/cassandra/1.2/webhelp/index.html#cassandra/architecture/a ...

  3. 数据同步gossip协议原理与应用场景介绍

    作者:京东物流 冯鸿儒 1 简介 Gossip是一种p2p的分布式协议.它的核心是在去中心化结构下,通过将信息部分传递,达到全集群的状态信息传播,传播的时间收敛在O(Log(N))以内,其中N是节点的 ...

  4. 【协议】5、gossip 协议

    Gossip是一种去中心化.容错并保证最终一致性的协议. Background:分布式环境 Gossip是为了解决分布式遇到的问题而设计的.由于服务和数据分布在不同的机器上,节点之间的每次交互都伴随着 ...

  5. Raft算法和Gossip协议

    简单介绍下集群数据同步,集群监控用到的两种常见算法. Raft算法 raft 集群中的每个节点都可以根据集群运行的情况在三种状态间切换:follower, candidate 与 leader.lea ...

  6. Hyperledger Fabric -- gossip 协议

    Hyperledger gossip   本文记述了Hyperledger Fabric 中 一种网络数据同步协议--gossip,它的主要作用是致力于账本数据的安全传输,保证不同节点之间状态的同步和 ...

  7. 【Consul】Consul架构-Gossip协议

    Consul使用gossip协议管理成员关系.广播消息到整个集群.详情可参考Serf library,Serf使用到的gossip协议可以参阅"SWIM: Scalable Weakly-c ...

  8. P2P 网络核心技术:Gossip 协议

    背景 Gossip protocol 也叫 Epidemic Protocol (流行病协议),实际上它还有很多别名,比如:“流言算法”.“疫情传播算法”等. 这个协议的作用就像其名字表示的意思一样, ...

  9. 浅谈集群版Redis和Gossip协议

    昨天的文章写了关于分布式系统中一致性哈希算法的问题,文末提了一下Redis-Cluster对于一致性哈希算法的实现方案,今天来看一下Redis-Cluster和其中的重要概念Gossip协议. 1.R ...

  10. Gossip协议

    Gossip数据传播协议: Fabric通过将工作负载划分到事务执行(背书和提交)对等节点和事务排序节点,优化了区块链网络性能.安全性和可伸缩性.这种网络操作的解耦需要一个安全.可靠和可伸缩的数据传播 ...

随机推荐

  1. Python3中的printable

    import string characters = string.printable # printable 是用作字符串常量的预初始化字符串.里面包含所有的标点符号,数字 print(charac ...

  2. 【Unity3D】消融特效

    1 前言 ​ 选中物体消融特效中基于 Shader 实现了消融特效,本文将基于 Shader Graph 实现消融特效,两者原理一样,只是表达方式不同,另外,选中物体消融特效中通过 discard 丢 ...

  3. chatgpt镜像站汇总 - 聚合GPT【即时更新】

    自荐下由我开发的聚合GPT网站,这边的GPT镜像站均为免费.无登录.无次数限制的!会及时剔除失效.添加可用地址[欢迎STAR.PR] 地址:https://ele-cat.gitee.io/comp- ...

  4. 一步步带你剖析Java中的Reader类

    本文分享自华为云社区<深入理解Java中的Reader类:一步步剖析>,作者:bug菌. 前言 在Java开发过程中,我们经常需要读取文件中的数据,而数据的读取需要一个合适的类进行处理.J ...

  5. 文心一言 VS 讯飞星火 VS chatgpt (122)-- 算法导论10.4 3题

    三.用go语言,给定一个n结点的二叉树,写出一个 O(n)时间的非递归过程,将该树每个结点的关键字输出.可以使用一个栈作为辅助数据结构. 文心一言: 以下是一个使用 Go 语言编写的函数,该函数使用一 ...

  6. mysql insert的特殊用法

    1. 正常的insert语句:插入一条数据如下:INSERT INTO `testdb`.`tb_user` (`id`, `userName`) VALUES (3, '张飞'); 2. inser ...

  7. 一个java文件的JVM之旅

    准备 我是小C同学编写得一个java文件,如何实现我的功能呢?需要去JVM(Java Virtual Machine)这个地方旅行. 变身 我高高兴兴的来到JVM,想要开始JVM之旅,它确说:&quo ...

  8. 解决ADS1.2与MDK4.7冲突问题

    需要添加2个系统变量. 1,在我的电脑点击属性--->高级--->环境变量---->系统变量,增加环境变量名: ARMCC5LIB 变量值:C:\Keil\ARM\ARMCC\lib ...

  9. RTMP协议学习——从握手到播放

    从客户端发起播放请求,到rtrmp视频流开始播放,大致经过了握手->建立连接->创建流->播放这几步比较重要的步骤.下面我将结合wireshark的抓包,对其中的每个流程进行分析和学 ...

  10. 题解 CF1264D1

    前言 数学符号约定: \(\dbinom{n}{m}\):表示 \(n\) 选 \(m\) . 如非特殊说明,将会按照上述约定书写符号. 题目分析: 考虑题目的问题弱一点的版本,假设此时我们的括号序列 ...