cassandra权威指南读书笔记--监控&维护
阅读原文时间:2023年07月09日阅读:2

cassandra SLF4J API记录日志,具体采用Logback实现。
在终端启动cassandra时,可以向程序输入-f,就能在终端看到这个输出。
Java Mangement Extensions,JMX。
JMX是java API,主要采用两种方式管理。首先利用JMX可以从内存,线程池和CPU等java应用通用的一些方面了解健康状况。其次,利用JMX可以分析应用中的监测的特定方面。
监测是指在应用代码外加一个包装器,从应用向JVM提供hook(钩子),使JVM能够收集数据供外部工具使用。包括监控代理,数据分析,性能分析等等。还可以更新值。
常用于:检测内存过低,堆空间,线程信息(死锁检测,峰值线程池和当前存活线程),详细的类加载器跟踪轨迹,日志级别控制,应用运行时间等。
很多应用都使用JMX监测,JVM,tomcat,cassandra等。
JDK包括一个MBean服务器,可以基于一个RPC向JMX管理应用提供监测特性。JVM还通过SNMP提供管理功能。不过也只能监控到有MBean的部分。
客户端工具可以通过jconsole连接cassandra,看到图像界面,看到MBean.
启用某个MBean,最好查看下java Doc,了解开启对性能有什么影响。

如果一个节点的schema version存在差异,通常意味着一个节点不可达或者宕机,需要重启。
堆推荐的大小至少8G,不建议超过32G.
设置好NTP很重要。
如果一个节点宕了,错过了一个删除操作,而且超过gc_grace_seconds时,节点上线恢复后就会“复活”本身已经被删除的僵尸数据。
修复过程:
运行nodetool repair,运行命令的节点会作为协调节点。org.apache.cassandra.service.ActiveRepairService类首先执行一个只读版本的主合并,即校验合并。期间节点会检查它的本地数据存储,并为每个副本(节点对某个表负责的range的数据)创建包含hash值的Merkle树,这部分在磁盘I/O开销很大(Cassandra使用了深度为15(2^15 = 32768个叶节点)的紧凑树版本)。之后,这个节点发起一个TreeRequest/TreeResponse会话与相邻的节点交换Merkle树。如果不同节点的Merkle树不一致,就必须调解来确定最后的数据值,然后所有节点都要设置为这个最后的值。如果发现不一致,节点之间会相互采用流传输方式传送不一致的数据,节点收到需要修复的数据时,会把数据存储在SSTable上。需要注意,如果一个表有大量的数据,merkle树的叶子的hash可能包含多个分区。比如,其中一个节点对这个表负责的range数据有100万个分区,那么每个Merkle树的叶子节点大约负责30个分区(100万/32768)。即使一个分区数据需要修复,也需要传整个叶子负责的数据,30个分区。这个原因导致在网络I/O方面开销很大。可能导致重复存储实际上不需要的数据。对于每一个表都需要在各个节点上重复这个过程,直到集群中所有的token range都已经修复。

完全修复,增量修复,反合并
2.1之前的版本,完成一个修复需要检查一个节点中所有的SSTable,即完全修复。2.1引入了做增量修复。增量修复,会将已修复的数据和未修复的数据分开,即反合并。
增量修复会减少要搜索的SSTable,自然Merkle树变小,stream传输减少。
Cassandra为每个SSTable文件增加一些元数据来跟踪修复状态。可以使用sstablemetadata + sstable文件名查看修复时间。
cassandra 2.2默认使用增量修复,除非使用-full执行。

顺序和并行修复
顺序修复即一次修复一个节点,并行修复就是一次修复包含相同数据的多个节点。2.2之前默认是顺序修复,2.2及以后默认是并行修复。动态snitch会自动选择响应快的节点响应请求,所以顺序修复(-seq)对请求的影响比并行修复(-par)小。
-pr的修复:对token range修复,因为如果执行所有的节点修复,会重复修复一些token range。
-st -et 修复:可以指定一个token段去修复。(需要注意driver的token range 某个range可能是从正值~负值,此时这个段需要切分,改为正值到Long.Max,Long.min到负值)

重建索引
使用二级索引,这些索引可能不同步。尽管cassandra在后台把二级索引存储为表,但是这些索引表只引用了存储在本地节点的值。由于二级索引不能修复,而且没有一种简单的方式来检查有效性,cassandra允许使用rebuild_index命令从头重建索引。可以在修复索引表之后重建索引。重建索引CPU和I/O开销也很大。

token
cassandra 2版本之后默认使用虚拟token,扩容或者缩容会自动重新分配token。如果使用单token节点,就需要手动重新配置令牌。使用nodetool move + 节点新的起始token,执行完再执行cleanup。

扩容
1、cassandra版本一致,如果是升级,就需要先扩容再升级,或者先升级在扩容。
2、cluster_name,dynamic_snitch,partitioner等需要一致
3、一般使用相同的种子节点
4、如果多机架,就需要平衡机架节点数,一起扩容
5、使用单token节点,需要手动nodetool move
6、立即扩容数据和移动token,组要把autobootsrap设置为true。如果没开启autobootsrap,可以手动执行nodetool bootstrap resume。
7、扩容完在所有老节点执行nodetool cleanup

新建DC
1、确保使用的endpoint_snitch支持多DC
2、在新的DC设置至少2个种子节点,并加入原种子节点列表。
3、设置token,可以和原来的DC不一样
4、设置autobootsrap设置为false
5、设置副本
6、在每个节点执行nodetool rebuild --dc

修复节点
1、如果节点故障时间小于max_hint_window_in_ms,就直接重启节点
2、故障时间大于max_hint_window_in_ms,但是小于gc_grace_seconds的最小值,那就重启节点,执行修复。
3、如果节点故障时间超过gc_grace_seconds,就应该replace这个节点,防止墓碑复活。

替换节点
扩容一个节点,修改cassandra-env.sh 增加如下:
JVM_OPTS=“$JVM_OPTS -Dcassandra.replace_address=


是所替换节点的主机名或者IP
替换完,数据拉取完之后,把这个配置删掉。
如果采用文件记录集群拓扑的snitch,如GossipingPropertyFileSnitch或PropertyFileSnitch,需要把新节点地址增加到每个节点的属性文件中,并对集群中的节点完成一个滚动重启。而且建议删除老节点之前先等待72小时,避免gossip困惑。
替换中子节点:直接把现有的一个非种子节点提升为种子节点,增加到cassandra.yaml的seeds中,旧的seeds去掉。然后再扩容一个非种子节点,或者replace掉降级为非种子的节点。

移除节点
decommission:在线退役,把属于自己节点的token区间分配给别的节点。退役完成会打印:DECOMMISSIONED(在线退役不会删除数据)
removenode:离线退役,如果使用虚拟token,集群会重新计算对应节点的token区间,并且复制副本数据到新的负责token的节点。如果没有使用虚拟token,需要手动调整分配给剩余各个节点的token区间(nodetool move),然后才能运行removenode来完成数据传输。
nodetool removenode + hostID
assassinate:离线退役,不复制数据。执行完,需要修复集群。
nodetool assassinate + IP

磁盘故障
使用多磁盘,可以用disk_failure_policy设置会确定发生磁盘故障时要采取什么行动。
1、stop:节点会停止gossip
2、die:JVM会退出,显示为DN
3、ignore:忽略错误
4、best_effort:打印warn日志,使用别的磁盘继续操作。JMX去监控org.apache.cassandra.db.BlacklistedDirectoriesMBean的状态,它会列出记录故障节点的目录
5、如果在节点启动时,设置的策略为best_effort以外的策略,会打印ERROR日志,并退出。

升级cassandra
仔细查看新版本主目录的NEWS.txt,遵循当前版本和新版本之间的版本升级说明。
滚动升级,一次升级一个节点
1、执行nodetool drain
2、停止这个节点
3、备份配置文件
4、安装新版本
5、在新版本配置文件中,把旧配置更新进去
6、如果是主版本号升级(以及一些次版本升级)需要在每个升级完的节点运行nodetool upgradesstables,将存储的数据文件转换为最新的格式,一般都需要升级节点的所有表。如果节点离线,还可以通过 bin/sstableupgrade脚本去升级这个节点的表。
注意:升级过程不要做修复和schema的更改。

备份和快照
建立快照会先flush,然后再创建硬链接。快照还包含manifest.json文件,列出这个快照包含的SSTable文件,用来确保一个快照的所有内容都存在。
自动快照功能:auto_snapshot,默认启用。可以在drop keyspace,drop table 或者Truncate时先创建快照。另外一个snapshot_before_compaction,默认是false。
清除快照:nodetool clearsnapshot.
增量备份:nodetool enablebackup, nodetool statusbackup,nodetool disablebackup。cassandra.yaml的incremental_backups设置为true。启用增量备份的时候,cassandra将SSTable flush的时候会创建备份,写到backups目录。

恢复快照和备份
一般恢复数据,会先删除表。然后如果集群拓朴和创建快照时相同,每个节点的token没有变化,当前表的副本因子也没有变化,就可以把SSTable数据文件复制到各个节点的data目录。然后可以通过运行nodetool refresh重新加载。
如果拓扑,token,副本因子有变化,需要用sstableloader的工具加载数据。
sstableloader表现得像一个节点:它也使用gossip协议来了解集群中的节点,不过它不把自己注册为一个节点。使用流传输将SSTable压入节点。sstableloader不直接将SSTable文件复制到每一个节点,而是把各个SSTable中的数据,插入到集群,让集群的分区器和复制策略发挥作用。
sstableloader对集群间移动数据也很有用。
注意:cassandra不把schema备份/快照作为一部分。任何恢复之前都必须确保有对应的schema。

SSTable工具
sstablemetadata、sstableloader、sstableupgrade。
sstableutil:列出指定表名的SSTable文件
sstablekeys:列出指定的SSTable中存储的分区键
sstableverify:校验指定表名的SSTable中存在错误或者数据破坏的文件,nodetool verify离线版本
sstablecrub:nodetool scrub离线版本,修复SSTable损坏的数据。如果修复完删了对应数据,需要执行repair
sstablerepairedset:用来标志指定的SSTable是否修复过,用来支持一个节点过渡到增量修复。增量修复2.2是默认配置,后续不再需要这个工具。
sstableexpieredblockers:找出阻塞删除SSTable的那个SSTable。知道为什么指定的SSTable还在磁盘上。
sstablelevelreset:将给定的SSTable级别重置为0,要求下次合并合并这些SSTable。
sstableofflinerelevel:使用LeveledCompactionStrategy为表重新分配SSTable级别。(比如批量导入的时候,就很有用)
sstablesplit:
sstablelevelreset、sstableofflinerelevel、sstablesplit,不在本地主机运行,需要修改。

集成和部署
计算存储大小:T=S* RF* CSF
S是前几章公式得到的表的大小,RF是副本因子,CSF对于压缩策略因子,SizeTieredCompactionStrategy策略最坏情况是所需数据都有第二个副本,所以是2,其他压缩策略是1.25。这样可以得到集群总容量。
开发环境建议最小8G内存,双核。生产环境建议至少:8核16GB.
存储建议SSD,避免使用共享存储:Storaget Area Network(SAN)和Network Attached Storage(NAS),不好扩展,耗费而外IO. 使用RAID0就够了,因为本身就有多副本能力。
网络健壮,推荐至少1GB以上的带宽。
正确配置NTP和服务器超时。不要在cassandra之上再做负载均衡,cassandra本身就有。
使用容器的时候,需要把数据目录配置在容器之外,这样,升级或者停止容器可以保留数据。容器一般默认使用软件定义路由,会降低cassandra的吞吐量,建议直接使用主机栈网络,带来限制是一个容器就部署一个cassandra节点。