Cassandra 架构
 
架构
关键词
首先有几个关键词:
KeyWord | Explain |
---|---|
Gossip | 集群中节点相互交换信息的通信协议 |
Partitioner | 决定在哪儿放置第一个副本 |
Snitch | 定义了复制策略用来放置副本和路由请求所使用的拓扑信息 |
Virtual nodes | 虚拟节点,用来避免热点以及提高宕机时数据转移效率 |
Token Ring | 令牌环 |
Gossip
Gossip用于在集群中节点间交换位置和状态信息。名字和“八卦”一样,大体上就是A告诉B自己的情况和自己知道的别人的情况,B转而告诉别人A告诉自己的情况与自己的情况,并以此进行下去。
Gossip每秒钟运行一次,与至多3个节点交换信息,这样所有节点可很快了解集群中的所有节点的信息。每个节点都会保存集群中的所有其他节点信息,这样随便连到哪一个节点,都能知道集群中的所有其他节点,因此客户端请求可以连接到集群中任意一节点。
通过Gossip还可检测节点是否正常以及性能,避免将请求路由至不可达或者性能差(需配置Dynamic Snitch)的节点。
一致性HASH
为了将数据放入指定节点,并且避免热点问题,引入了一致性HASH。如图:

在节点很多时,这能够保证数据分布均匀,但是如果节点很少,可能因为节点分布不均导致数据倾斜,因此在一致性HASH的技术上引入虚拟节点(vnode)概念。
把每个节点分为v个虚拟节点,然后再对每一个虚拟节点进行上面所述的HASH并分配到HASH空间环上。
vnode



目前Cassandra提供了两种复制策略:
SimpleStrategy:用于单数据中心,第一个副本放在某个节点,其他副本放在HASH中顺时针的近邻节点。
NetworkTopologyStrategy:用于多数据中心,可以指定每个数据中心存放多少个副本。
在创建keyspace时需要指定复制策略:
1 | CREATE KEYSPACE Excelsior WITH REPLICATION = { 'class' : 'SimpleStrategy','replication_factor' : 3 }; |
其中数据中心名需要与snitch中配置吻合。
Partitioners
Cassandra中每一行由唯一的主键标识,partitioner相当于用来计算主键token的hash函数。Cassandra依据这个token值在集群中放置对应的行。目前有三种partitioner:
Murmur3Partitioner:当前的默认值,依据MurmurHash哈希值在集群中均匀分布数据。(推荐使用)
RandomPartitioner:依据MD5哈希值在集群中均匀分布数据。
ByteOrderedPartitioner:依据行key的字节从字面上在集群中顺序分布数据。(不推荐使用)
注意:若使用虚拟节点(vnodes)则无需手工计算tokens。若不使用虚拟节点则必须手工计算tokens将所得的值指派给cassandra.ymal主配置文件中的initial_token参数。
Snitches
snitch决定了节点属于哪个数据中心或者机架。提供网络拓扑信息,用以确定向/从哪个数据中心或者网架写入/读取数据。
注意:
- 所有节点需用相同的snitch;
- 集群中已插入数据后由更改了snitch则需运行一次fullrepair。
几种常用的snitch:
Dynamic snitching:监控从不同副本读操作的性能,选择性能最好的副本。dynamic snitch默认开启,所有其他snitch会默认使用dynamic snitch 层。
SimpleSnitch:默认值,用于单数据中心部署,不使用数据中心和网架信息。使用该值时keyspace复制策略中唯一需指定的是replication factor
RackInferringSnitch:根据数据中心和网架确定节点位置,而数据中心及网架信息又由节点的IP地址隐含指示。
PropertyFileSnitch:根据数据中心和网架确定节点位置,而网络拓扑信息又由用户定义的配置文件cassandra-topology.properties 获取。在节点IP地址格式不统一无法隐含指示数据中心及网架信息或者复杂的复制组中使用该值。
GossipingPropertyFileSnitch:产品中推荐使用。通过cassandra-rackdc.properties中信息确定本机机架和数据中心,并且使用Gossip通知其他节点。为了方便从PropertyFileSnitch迁移,优先使用
cassandra-topology.properties中配置,迁移完成后记得删除。
写流程
单节点写示例

首先客户端向集群中任意一个节点发送查询命令,这个节点充当客户端和读写节点间的协调者(coordinator)。Coordinator根据集群配置决定请求分发到环中具体哪些节点上。由于副本因子为3,所以有三个节点保存副本,假设为1、3、6。数据分发到三个节点并写入,因为一致性为ONE,所以任何一个节点写入完成则返回,其他节点在后台继续写入直到完成。
多数据中心的写实例

读流程

内部实现
数据结构
内部使用了LSM树结构,LSM树的设计思想非常朴素:将对数据的修改增量保持在内存中,达到指定的大小限制后将这些修改操作批量写入磁盘。因此,LSM树有个很大的好处,就是避免询盘开销,大大提高的写入性能。基于LSM树实现的HBase的写性能比Mysql高了一个数量级,读性能低了一个数量级。
写操作
通过在多个同级节点创建数据的多个副本保证可靠性和容错。表是非关系型的,无需过多额外工作来维护关联的表的完整性,因此写操作较关系型数据库快很多。

更新


删除
删除操作不会理解从硬盘上删除数据,而是会被tombstone标记以指定其状态,它会存在一定的时间(由gc_grace_seconds指定),超出该时间后compaction进程永久删除该column。
若删除期间节点down掉,被标记为tombstone的column会发送信号给Cassandra使其重发删除请求给该replica节点。若replica在gc_grace_seconds期间复活,会最终受到删除请求,若replica在gc_grace_seconds之后复活,节点可能错过删除请求,而在节点恢复后立即删除数据。需定期执行节点修复操作来避免删除数据重现。
hinted handoff writes
在不要求一致性时确保写的高可用,在cassandra.yaml中开启该功能。执行write操作时若拥有对应row的replica down掉了或者无回应,则协调者会在本地的system.hints表中存储一个hint,指示该写操作需在不可用的replica恢复后重新执行。默认hints保存3小时,可通过max_hint_window_in_ms改变该值。提示的write不计入consistencylevel中的ONE,QUORUM或ALL,但计入ANY。ANY一致性级别可确保cassandra在所有replica不可用时仍可接受write,并且在适当的replica可用且收到hint重放后该write操作可读。移除节点后节点对应的hints自动移除,删除表后对应的hints也会被移除。仍需定期执行repair(避免硬件故障造成的数据丢失)
读数据
Cassandra推荐使用SSD,以partition key读/写,消除了关系型数据库中复杂的查询。

- 找到。从compression offset map中查找拥有对应数据的压缩块。从磁盘取出压缩的数据,返回结果集。
- 未找到。搜索Partition summary(partition index的样本集)确定index条目在磁盘中的近似位置。从磁盘中SSTable内取出index条目。从compression offset map中查找拥有对应数据的压缩块。从磁盘取出压缩的数据,返回结果集。


例如,要更新包含用户数据的某个row中的email 列,cassandra并不重写整个row到新的数据文件,而仅仅将新的email写进新的数据文件,username等仍处于旧的数据文件中。上图中红线表示Cassandra需要整合的row的片段用以产生用户请求的结果。为节省CPU和磁盘I/O,Cassandra会缓存合并后的结果,且可直接在该cache中更新row而不用重新合并。