Cassandra集群没有中心节点,各个节点的地位完全相同,它们通过一种叫做gossip的协议维护集群的状态。通过gossip,每个节点都能知道集群中包含哪些节点,以及这些节点的状态,这使得Cassandra集群中的任何一个节点都可以完成任意key的路由,任意一个节点不可用都不会造成灾难性的后果。

一、Gossip算法背景

Gossip算法如其名,灵感来自办公室八卦,只要一个人八卦一下,在有限的时间内所有的人都会知道该八卦的信息,这种方式也与病毒传播类似,因此Gossip有众多的别名“闲话算法”、“疫情传播算法”、“病毒感染算法”、“谣言传播算法”。但Gossip并不是一个新东西,之前的泛洪查找、路由算法都归属于这个范畴,不同的是Gossip给这类算法提供了明确的语义、具体实施方法及收敛性证明。

二、Gossip算法特点

Gossip算法又被称为反熵(Anti-Entropy),熵是物理学上的一个概念,代表杂乱无章,而反熵就是在杂乱无章中寻求一致,这充分说明了Gossip的特点:在一个有界网络中,每个节点都随机地与其他节点通信,经过一番杂乱无章的通信,最终所有节点的状态都会达成一致(很神奇)。每个节点可能知道所有其他节点,也可能仅知道几个邻居节点,只要这些节点可以通过网络连通,最终他们的状态都是一致的。

三、Gossip本质

Gossip是一个带冗余的容错算法,更进一步,Gossip是一个最终一致性算法。虽然无法保证在某个时刻所有节点状态一致,但可以保证在“最终”所有节点一致,“最终”是一个现实中存在,但理论上无法证明的时间点。因此Gossip适合没有很高一致性要求的场景。

因为Gossip不要求节点知道所有其他节点,因此又具有去中心化的特点,节点之间完全对等,不需要任何的中心节点。实际上Gossip可以用于众多能接受“最终一致性”的领域:失败检测、路由同步、Pub/Sub、动态负载均衡。

但Gossip的缺点也很明显,冗余通信会对网路带宽、CUP资源造成很大的负载,而这些负载又受限于通信频率,该频率又影响着算法收敛的速度。

四、Gossip节点的通信方式及收敛性

Gossip中的每个节点维护一组状态,状态可以用一个key/value对表示,还附带一个版本号,版本号大的状态比版本号小的新。两个节点(A、B)之间存在以下三种通信方式:

通信方式

含义

push

A节点将数据(key,value,version)及对应的版本号推送给B节点,B节点更新A发过来的数据中比自己新的数据

pull

A不发送数据的value,仅发送数据的摘要key和version给B。B根据版本比较数据,将本地比A新的数据(key,value,version)推送给A,A更新自己的本地数据

push/pull

与pull类似,A仅发送摘要给B。不同之处在于,B比较版本后,不仅将比A新的数据发送给A,同时还向A请求A的摘要中比自己新的数据

如果把两个节点数据同步一次定义为一个周期,则在一个周期内,push需通信1次,pull需2次,push/pull则需3次,从效果上来讲,push/pull最好,理论上一个周期内可以使两个节点完全一致。直观上也感觉,push/pull的收敛速度是最快的。

假设每个节点通信周期都能选择(感染)一个新节点,则Gossip算法退化为一个二分查找过程,每个周期构成一个平衡二叉树,收敛速度为O(n2),对应的时间开销则为O(logn)。这也是Gossip理论上最优的收敛速度。但在实际情况中最优收敛速度是很难达到的。

显然pull的收敛速度大于push,而每个节点在每个周期被感染的概率都是固定的p(0<p<1),因此Gossip算法是基于p的平方收敛,也成为概率收敛,这在众多的一致性算法中是非常独特的。

Gossip的节点的工作方式又分为以下两种:

Anti-Entropy(反熵):以固定的概率传播所有的数据

Rumor-Mongering(谣言传播):仅传播新到达的数据

Anti-Entropy模式有完全的容错性,但有较大的网络、CPU负载;Rumor-Mongering模式有较小的网络、CPU负载,但必须为数据定义”最新“的边界,并且难以保证完全容错,对失败重启且超过”最新“期限的节点,无法保证最终一致性,或需要引入额外的机制处理不一致性。

五、cassandra中Gossip的节点同步规则

当一个节点启动时,获取配置文件中的seeds配置。cassandra作为一个去中心化的分布式系统,没有中心节点的存在。但为了让节点启动时能与集群通信,仍然需要为它配置最少一个seed节点。

Cassandra内部有一个Gossiper,每隔一秒运行一次(在Gossiper.java的start方法中),按照以下规则向其他节点发送同步消息:

1.随机取一个当前活着的节点,并向它发送同步请求

2.随机取一个不可达的节点,并向它们发送同步请求

3.如果第一步中所选择的节点不是seed,或者当前活着的节点数少于seed数,则向随意一台seed发送同步请求

第一步的目的是和目前活着的节点同步状态,第二步的目的是尽快发现已下线的节点重新上线了。第三步中的第一个条件,是因为seed理论上总是有较多的节点状态信息,若第一次同步的节点不是seed,则应该再和seed同步一下。第三步中的第二个条件则是为了避免出现seed孤岛。

如果没有这个判断,考虑这样一种场景,有4台机器,{A,B,C,D},并且配置了它们都是seed,如果它们同时启动,可能会出现这样的情形:

A节点起来,发现没有活着的节点,走到第三步,和任意一个种子同步,假设选择了B。B节点和A完成同步,则认为A活着,它将和A同步,由于A是种子,B将不再和其他种子同步。C节点起来,发现没有活着的节点,同样走到第三步,和任意一个种子同步,假设这次选择了D。C节点和D完成同步,认为D活着,则它将和D同步,由于D也是种子,所以C也不再和其他种子同步。

这时就形成了两个孤岛,A和B互相同步,C和D之间互相同步,但是{A,B}和{C,D}之间将不再互相同步,它们也就不知道对方的存在了。

加入第二个判断后,A和B同步完,发现只有一个节点活着,但是seed有4个,这时会再和任意一个seed通信,从而打破这个孤岛。

六、cassandra中Gossip的实现

Cassandra采用的通信方式是push/pull,如前文所述,push/pull有三个阶段。在每个阶段,节点之间都需要传递一些自己的状态信息。状态信息的传递是通过封装在一种特定的消息里传递,每个阶段传递的消息格式均不同,如下表:

消息名

含义

GossipDigitsSynMessage

A向B请求同步

GossipDigitsAckMessage

B返回自己拥有的比A新的数据给A

GossipDigitsAck2Message

A再返回自己拥有的比B新的数据给B

Gossip互相之间通信,通过上表的消息封装需要传递的信息。节点间互相交换的状态信息主要有以下3种:

状态信息

含义

HeartBeat

心跳信息,由generation和version组成。generation每次系统启动都加1,用于区分重启前后的状态

ApplicationState

用于表示系统状态,存储系统的负载信息等

EndPointState

维护节点自身数据的全局version,并封装HeartBeat和ApplicationState

Cassandra的每个节点都实现了IEndPointStateChangeSubscriber接口的,它负责处理接收到的消息,该接口包含以下方法:

方法名

含义

onjoin

有机器加入到集群中

onChange

有状态发生变更了

onAlive

机器可用

onDead

机器不可用

下图所示是两个cassandra节点之间通过gossip进行状态同步的完整过程。

这里假设192.168.1.1(源节点)决定和192.168.1.2(目标节点)同步,首先源节点向目标节点发送GossipDigestSynMessage包,这个包有本机维护的所有节点的状态信息的最新版本摘要,摘要只包含key和version,不包含具体的value,这样可以减小同步的带宽消耗。

当目标节点收到GossipDigestSynMessage包时,它需要做两件事:

1.找出收到的消息中比本地版本新的状态,按照版本号差异大小排序,将这些状态的摘要放入GossipDigestAckMessage中。

2.找出本地比源节点版本更新的状态,放入GossipDigestAckMessage中,并将它发送回源节点。

这里按照版本号差异大小排序的原因是每个Message允许发送的状态数量是有限的(参见Gossip.java中的MAX_GOSSIP_PACKET_SIZE定义),这样可以保证比较老的状态(版本号差异大的)可以优先得到更新。

源机器接收到GossipDigestAckMessage后,同样也做两件事:

1.使用目标节点发送过来的比自己新的状态更新本地的状态,源节点获取到了目标节点上比自己更新的状态。

2.源节点把包含在GossipDigestAckMessage中,目标节点向自己请求更新的摘要对应的状态信息通过GossipDigestAck2Message发送到目标服务器。

目标服务器更新本地的状态,这样目标服务器也获取到了源节点上比自己更新的状态。完成这样一次同步后,源节点和目标节点上的状态都得到了同步。

cassandra学习笔记五相关推荐

  1. python函数是一段具有特定功能的语句组_Python学习笔记(五)函数和代码复用

    本文将为您描述Python学习笔记(五)函数和代码复用,具体完成步骤: 函数能提高应用的模块性,和代码的重复利用率.在很多高级语言中,都可以使用函数实现多种功能.在之前的学习中,相信你已经知道Pyth ...

  2. Ethernet/IP 学习笔记五

    Ethernet/IP 学习笔记五 Accessing data within a device using a non-time critical message (an explicit mess ...

  3. StackExchange.Redis学习笔记(五) 发布和订阅

    StackExchange.Redis学习笔记(五) 发布和订阅 原文:StackExchange.Redis学习笔记(五) 发布和订阅 Redis命令中的Pub/Sub Redis在 2.0之后的版 ...

  4. 吴恩达《机器学习》学习笔记五——逻辑回归

    吴恩达<机器学习>学习笔记五--逻辑回归 一. 分类(classification) 1.定义 2.阈值 二. 逻辑(logistic)回归假设函数 1.假设的表达式 2.假设表达式的意义 ...

  5. 好程序员教程分析Vue学习笔记五

    好程序员教程分析Vue学习笔记五,上次我们学习了Vue的组件,这次我们来学习一下路由的使用.在Vue中,所谓的路由其实跟其他的框架中的路由的概念差不多,即指跳转的路径. 注意:在Vue中,要使用路由, ...

  6. 【AngularJs学习笔记五】AngularJS从构建项目开始

    为什么80%的码农都做不了架构师?>>>    #0 系列目录# AngularJs学习笔记 [AngularJs学习笔记一]Bower解决js的依赖管理 [AngularJs学习笔 ...

  7. ROS学习笔记五:理解ROS topics

    ROS学习笔记五:理解ROS topics 本节主要介绍ROS topics并且使用rostopic和rqt_plot命令行工具. 例子展示 roscore 首先运行roscore系列服务,这是使用R ...

  8. Spring Boot 框架学习笔记(五)( SpringSecurity安全框架 )

    Spring Boot 框架学习笔记(五) SpringSecurity安全框架 概述 作用 开发示例: 1. 新建项目 2. 引入依赖 3. 编写`SecurityConfig`类,实现认证,授权, ...

  9. Java学习笔记(五):一张图总结完JVM8基础概念

    Java学习笔记(五):一张图总结完JVM8基础概念 引文 最近在学习JVM的相关内容,好不容易把基础概念全部都学了一遍,却发现知识网络是零零散散的.迫不得已,只好再来一次总的归纳总结.为了更好的理解 ...

最新文章

  1. gulp-sass_如果您是初学者,如何使用命令行设置Gulp-sass
  2. 计算机 二进制 中国,二进制与计算机
  3. linux环境搭建seafile客户端自动上传文件
  4. WinForm创建系统托盘以及操作注册表
  5. selenium python怎么读_selenium+Python中的面试总结
  6. ios开发笔记之 APNS推送服务的实现
  7. centos 设置双网卡,双网关
  8. async js 返回值_JS异步编程 | Async / Await / Generator 实现原理解析
  9. wxWidgets:线程间和进程间通信
  10. Python入门之数据类型
  11. 22504!Windows 11 新预览版发布
  12. 第八十二期:掌握这些监控报警优化技巧,百万年薪不在话下!
  13. IDEA上Debug调试全流程
  14. 鸿蒙系统发布会16号几点,华为鸿蒙手机系统正式定档发布,12月16日于我们见面...
  15. 诺基亚9 PureView五摄机皇再曝光 低配高价毫无诚意?
  16. C#限制float有两位小数
  17. 《深入理解Windows操作系统》笔记1
  18. CAD将图形输出成png图片的三种方法
  19. 项目管理java_java项目管理经验总结
  20. REVIT插件 | 建模助手这次的版本更新,BIMer都笑了

热门文章

  1. 某虚拟化项目中思科与华为交换机链路聚合互连案例
  2. .net使用正则表达式校验、匹配字符工具类
  3. as 使用类模拟枚举类
  4. 轻松scrum之旅 思维导图读书笔记
  5. 说明书 Cisco wrv210
  6. 把你的火狐浏览器改成Chrome样式
  7. 【修真院WEB小课堂】定时器有哪些用法?
  8. Apahce服务器配置非根目录的虚拟目录
  9. 深入探索 IBM 数据分析和预测软件 - PASW Modeler
  10. LeetCode 504. Base 7 (C++)