cassandra权威指南读书笔记--Cassandra架构(2)

环和令牌
cassandra的数据管理是用一个环来表示。为环中的每个节点分配一or多个数据范围,用token描述。token由64位整数ID表示,范围-2^(63)~2^(63)-1。使用对分区键进行一个hash来计算分区键落到哪个token中,进而决定分配到哪个节点。org.apache.cassandra.dht.Range类。
虚拟节点(vnode),1.2版本引入,2.0默认开启。一个token就是对应一个vnode。将环分解为虚拟节点数的分段,可以让数据分布更均匀,在扩容,缩容,修复都会更快,不仅仅依赖一个节点的数据。num_tokens用来配置,可以让性能强的机器分配多,性能弱的分配少。
org.apache.cassandra.dht.tokenallocator.ReplicationAwareTokenAllocator。

分区器(全局配置)
决定分区键怎么hash。org.apache.cassandra.dht(DHT表示分布式哈希表)。
1.2增加Murmur3Partitioner,默认分区器。生成64哈希值。之前默认分区器RandomParttioner.
可插拔,可自定义。

复制策略
多副本,第一个副本肯定是根据分区键找到的hash环所在的节点上,剩下的副本就得根据复制策略放置。允许扩展,实现org.apache.cassandra.locator.AbstractReplicationStrategy。现在主要实现:SimpleStragety和NetworkTopologyStragety。
SimpleStragety:从分区键的所在环,往后找连续的节点上。
NetworkTopologyStragety:允许为每个数据中心指定一个不同的副本因子,DCXXX:几副本。如果是同一个数据中心,会适当的分配到不同机架。

一致性
ONE,TWO,THREE,QUORUM,LOCAL_QUORUM,ALL,ANY,SERIAL。
一般认为ALL和QURUM是强一致性。R+W>N 即强一致性。R,读副本数;W,写副本数;N,副本因子。
QUORUM:副本因子/2+1;需要多少个节点响应成功才算读写成功。其中写操作,在响应写成功之后,还会继续在后台更新其他副本。
级别:SERIAL
描述:允许读取当前的(包括uncommitted的)数据,如果读的过程中发现uncommitted的事务,则commit它。 用法:轻量级事务。

查询和协调节点
cassandra每个节点都对等,每个节点都可以接收客户端请求,然后转发到对应请求数据所在节点,这就是协调节点。协调节点会合并请求结果返回给客户端。

Memtable,SSTable和commitLog
cassandra节点:
JVM:memtable,键缓存,行缓存,计数器缓存
键缓存存储了分区键和行索引之间的一个映射。以利于更快的访问存储在磁盘上的SSTable。可以对每个表分别配置键缓存的使用。
行缓存可以缓存整个行,对于频繁访问的行,行缓存可以提高读访问的速度,但代价是要使用更多的内存。
计数器缓存通过减少对最常访问的计数器的锁竞争来提高计数器性能。
磁盘:commitLog,SSTable,hint(2.2+)
写操作,先写commitlog,commitlog支持持久性的一种失败恢复机制。写日志成功才算成功。节点重启会把commitlog重放,读取SSTable,保证数据不会丢。
commitLog
属于单个节点。commitlog_sync有2种策略:periodic,group和 batch。默认periodic,表示服务器只按指定的间隔保证写操作是持久的。这个间隔时间由commitlog_sync_perion_in_ms属性指定,默认10000(10秒)。倘若服务器设置为只是在周期时间内保证写操作是持久的,就有可能丢失一些数据,因为在这个周期时间里,那些数据可能还没有从"后台写"(write-behind),缓存同步到磁盘。如果设置为batch,则会阻塞,直到写操作同步到磁盘(提交日志同步到磁盘完成之前,Cassandra不会确认写操作完成),如果要求更快地写,就会限制它管理自己资源的自由。修改为batch,需要设置commitlog_sync_batch_window_in_ms为一个合理的值,每次同步的间隔时间。group和btach类似,也会阻塞。
先写commitlog,再写memtable。每个memtable包含一个特定的表的数据。早前memtable放在JVM堆中。2.1开始把memtable放到原生内存中。这样cassandra不容易受到java垃圾回收的影响。存在memtable的对象达到阈值,就会把内容输出到SSTable上,然后再创建新的memtable。这个输出是非阻塞的:一个表会对应多个memtable,其中一个是当前的memtable,剩下都是等待刷新到磁盘上的。(负载过高会影响刷盘)。
commitlog会为每个表保存一个标志位,第一次写操作时会写入日志,设置为1。当一个memtable正确输出到磁盘,相应的提交位会设置为0。所以是用来表示一个表是否把数据刷盘,表示commitlog不需要再维护这个数据来支持持久性。还有int[] lastFlushedAt,表示恢复从哪里开始。
SSTable是从Google的bigtable借用的。SSTable一旦形成,内容就不可改变,合并也只是改变磁盘的表示,把数据重新归并,然后删除老的sstable。
cassandra写性能高是因为追加写,然后通过合并来提高读的性能。读会读memtable和SSTable。Memtable由org.apache.cassandra.db.Memtable实现。

缓存
键缓存
存储了分区键和行索引之间的一个映射。以利于更快的访问存储在磁盘上的SSTable。可以对每个表分别配置键缓存的使用。JVM堆内。
行缓存
可以缓存整个行,对于频繁访问的行,行缓存可以提高读访问的速度,但代价是要使用更多的内存。存在堆外内存。
计数器缓存(2.1新增)
通过减少对最常访问的计数器的锁竞争来提高计数器性能。
默认启用键缓存和计数器缓存,行缓存是禁用的。

Hinted handoff
某个节点故障不可用,协调节点会记录对应的hint数据,等对应节点恢复,会发送写请求。cassandra为写的每个分区保留一个单独的hint。
一致性是ANY时,写hint成功,也算写成功。只是在节点恢复之前没法读。
Hinted handoff日志是节点恢复之后,进行数据传输是显示的。
防止hint堆积,可以禁止hint或者设置节点故障多久之内还写hint。节点恢复会发送大量hint。
org.apache.cassandra.db.HintedHandOffManager.

轻量级事务和Paxos
2.0支持一种提供线性一致性的轻量级事务或者“LWT”机制,基于单决策的paxos(单决策的分布式共识算法)。
在单决策的paxos(准备/承诺-->提议/接受)上,补充准备/承诺-->读-->提议/接受-->提交确认。协调节点会作为领导者提交提议。paxos来支持“写前读”。
关键是领导者必须先提交这个提议之前的所有在处理的提议。LWT涉及协调节点和副本之间的4次通信。比正常开销写大,谨慎使用。
LWT仅限于一个分区内,cassandra会为各个分区存储一个paxos状态,保证不同分区不会相互干扰。

墓碑
软删除,删除会先记录为墓碑。所以删除也是追加写,速度快。
GCGraceSeconds,超过这个时间,墓碑就会被回收。这是节点故障(坏盘导致的墓碑丢失)会恢复时间。默认864000秒,10天。如果超过那么久还没有恢复,要视为故障节点并替换才行。

布隆过滤器
布隆过滤器用来提升读性能的。布隆过滤器是检查一个元素是否属于一个集合的一种非确定性算法,速度非常快。非确定是因为,有可能得到假阳性(误报),但是不会假阴性(漏报),即会杀错,但不放过。
布隆过滤器使用一个hash函数将一个数据集中的值映射到一个位数组,并将一个较大的数据集缩减位一个摘要字符串。布隆过滤器会缓存在磁盘中,访问磁盘之前会访问布隆过滤器,减少查找键而访问磁盘。org.apache.cassandra.utils.BloomFilter

合并
合并SSTable数据时,键会归并,列会组合,墓碑被删除,会创建一个新的索引。释放空间。
合并会对归并的数据排序,在排序数据上创建新索引,然后将归并后有序的数据并且有索引的全新数据写入新的SSTable(包括:数据,索引和过滤器)org.apache.cassandra.db.compaction.CompationManager.
合并可以减少SSTable的查找。合并时,IO是会有临时峰值,因为读老的SSTable,写新的SSTable。
合并算法:每个表单独配置。扩展AbstractCompactionStragtegy。
默认是STCS,SizeTieredCompactionStrategy,适用写密集的表。
LCS,LeveledCompactionStrategy,适用读密集的表。DTCS,DateTieredCompactionStrategy,适用于时间序列或者基于日期的数据。2.1增加了反合并的特性。修复(repair)会把一个SSTable划分为2个SSTable,一个包含修复后的数据,一个包含未修复的数据。必须分别处理已修复和未修复的SSTable,使它们不会合并在一起。

逆熵,修复和Merkle树
修复包括读修复和逆熵修复(即手动修复,nodetool repair)。逆熵:变有序,一致。
读取数据会检查副本是否有过期数据,如果有最新值的节点数不够就会读修复。
nodetool repair会触发cassandra的主合并,在服务器发起一个TreeRequest/TreeResponse会话,与对应副本之间的节点交换Merkle树。Merkle树是表示这个表中数据的一个hash树。如果不同节点的树不匹配,就必须修复。
Merkle树的比较校验由org.apache.cassandra.service.AbstractReadExecutor负责。
Merkle树,即hash树,可做完整性校验。叶子节点是数据块,通常是系统中的文件。父节点就是直接子节点的一个hash。对比,即先对比根节点,如果根节点都不一样,再看到底是左儿子不一样还是右儿子不一样。org.apache.cassandra.utils.MerkleTree实现。Merkle树可以确保cassandra节点的对等网络可以无修改并且安全地接收数据块。Merkle树也用来在密码学中检验文件和传输的内容。
cassandra每个表有自己的Merkle树,这个树在主合并期间创建为一个快照,Merkle树生命周期仅限于发送给副本因子所在节点的时候,好处是可以减少网络IO(只发送一个树的摘要,比发送所有数据少了很多IO)。

posted @ 2020-07-12 23:44  DevinDC  阅读(473)  评论(0编辑  收藏  举报