Cassandra Gossiper协议

Cassandra 集群使用Gossip协议维护集群状态  各个节点之间是平等的  并非如同hadoop一样存在主从之分

通过Gossip协议可以知道集群中各个节点的当前状态 

Cassandra中的GossipTask类主要实现了节点间消息通信机制  

// wait on messaging service to start listening
MessagingService.instance().waitUntilListening();

/* Update the local heartbeat counter. */
endpointStateMap.get(FBUtilities.getBroadcastAddress())
                .getHeartBeatState().updateHeartBeat();


final List<GossipDigest> gDigests = new ArrayList<GossipDigest>();
Gossiper.instance.makeRandomGossipDigest(gDigests);

if (gDigests.size() > 0)
{
    GossipDigestSyn digestSynMessage = new GossipDigestSyn(
            DatabaseDescriptor.getClusterName(),
            DatabaseDescriptor.getPartitionerName(),
            gDigests);    

    MessageOut<GossipDigestSyn> message = new MessageOut<GossipDigestSyn>(
        MessagingService.Verb.GOSSIP_DIGEST_SYN,
        digestSynMessage,
        GossipDigestSyn.serializer);

    /* Gossip to some random live member */
    boolean gossipedToSeed = doGossipToLiveMember(message);

    /* Gossip to some unreachable member to check if he is back up */
    doGossipToUnreachableMember(message);

                    
    if (!gossipedToSeed || liveEndpoints.size() < seeds.size())
        doGossipToSeed(message);

    doStatusCheck();
}


看看sendGossip方法的是实现:

List<InetAddress> liveEndpoints = ImmutableList.copyOf(epSet);
int size = liveEndpoints.size();
...
        
/* Generate a random number from 0 -> size */
int index = (size == 1) ? 0 : random.nextInt(size);
InetAddress to = liveEndpoints.get(index);
MessagingService.instance().sendOneWay(message, to);


MessagingService sendOneWay方法实现部分 

主要部分如下所示  简单说就是先获取一个连接再把需要发送的连接放进队列

其中connectionManagers是一个 ConcurrentMap<InetAddress, OutboundTcpConnectionPool>

用来存储Address到ConnectionPool的映射表

enqueue的时候会先检查队列长度 大于1024 会触发expireMessages机制

另队列中的消息包装成了QueuedMessage结构

// get pooled connection (really, connection queue)
OutboundTcpConnection connection = getConnection(to, processedMessage);

// write it
connection.enqueue(processedMessage, id);



SinkManager类主要用来做message集合使用


Gossip 协议交换过程

29153958_V0iD.gif


节点在开始交换Gossip信息的时候 首先发送一个GossipDigestSynMessage

GossipDigestSyn digestSynMessage = new GossipDigestSyn(
        DatabaseDescriptor.getClusterName(),
        DatabaseDescriptor.getPartitionerName(),gDigests);

MessageOut<GossipDigestSyn> message = new MessageOut<GossipDigestSyn>(
        MessagingService.Verb.GOSSIP_DIGEST_SYN,
        digestSynMessage,GossipDigestSyn.serializer);


当有节点收到GossipDigestSynMessage时  使用GossipDigestAckMessage回复消息

GossipDigestAckMessage其中主要包含两部分:GossipDigest列表和InetAddress --> EndpointState映射

final List<GossipDigest> gDigestList;
final Map<InetAddress, EndpointState> epStateMap;


具体的处理过程以IVerbHandler的形式注册到MessagingService上 

verbHandler.doVerb(message, id);// 具体调用相应MessageHandler





参考资料:

[ArchitectureGossip] http://wiki.apache.org/cassandra/ArchitectureGossip

[internode communication]  http://www.datastax.com/documentation/cassandra/1.2/cassandra/architecture/architectureGossipAbout_c.html

[Cassandra中Gossip具体实现方式] http://blog.csdn.net/zhangzhaokun/article/details/5859760



转载于:https://my.oschina.net/darionyaphet/blog/337588

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值