Docker版Cassandra4.0.1恢复含索引快照报分区器不匹配错误
问题现象
通过nodetool snapshot命令生成Cassandra数据快照,尝试在Docker部署的Cassandra 4.0.1容器中恢复数据时,最初停止容器执行nodetool repair操作就发现部分表抛出报错,后续调整恢复流程拷贝索引文件执行refresh时同样触发该错误。报错信息如下:
partitioner org.apache.cassandra.dht.LocalPartitioner does not match system partitioner org.apache.cassandra.dht.Murmur3Partitioner. Note that the default partitioner starting with Cassandra 1.2 is Murmur3Partitioner, so you will need to edit that to match your old partitioner if upgrading.
运行环境信息
INFO [main] 2022-07-07 11:54:10,806 StorageService.java:734 - Cassandra version: 4.0.1 INFO [main] 2022-07-07 11:54:10,806 StorageService.java:735 - CQL version: 3.4.5 INFO [main] 2022-07-07 11:54:10,806 StorageService.java:736 - Native protocol supported versions: 3/v3, 4/v4, 5/v5, 6/v6-beta (default: 5/v5)
待恢复的表包含二级索引,索引数据也以SSTable格式备份在隐藏目录中。
已执行的错误操作流程
- 停止运行中的Cassandra容器
- 将备份的表文件、索引文件全部拷贝至容器内对应keyspace下目标表的根数据目录
- 启动Cassandra容器
- 执行
nodetool refresh ks ts命令加载数据,执行后触发上述报错
执行的具体操作命令:
docker stop cassandra docker cp backup_table cassandra:/var/lib/cassandra/data/{keyspace_name}/{table_name} docker start cassandra docker exec cassandra nodetool refresh ks ts
报错根因
- 该报错和集群版本升级、全局分区器配置错误无关,核心原因是文件放置路径错误:
- Cassandra全局默认使用
Murmur3Partitioner处理主表数据分区,而二级索引的SSTable本身就使用LocalPartitioner,且索引文件必须存放在主表目录下以.索引名命名的独立隐藏子目录中,不能和主表SSTable文件放在同一层级。 - 之前的恢复操作把二级索引的SSTable文件直接拷贝到了主表的根数据目录,Cassandra在执行repair、refresh等操作扫描主表SSTable时,会把同目录下的索引文件识别为主表SSTable,校验分区器时发现文件标记的
LocalPartitioner和系统全局的Murmur3Partitioner不匹配,直接抛出异常。
正确的快照恢复方案
- 提前在目标Cassandra实例上创建和源端完全一致的keyspace、表结构、二级索引,确保表schema、索引名称和快照生成时完全一致,不要提前修改表结构。
- 停止目标Cassandra容器:
docker stop cassandra - 清理目标路径下的旧文件,按规则放置备份文件:
- 主表SSTable文件(数据文件、校验文件、元数据文件等)放到主表对应目录:
/var/lib/cassandra/data/<keyspace_name>/<table_name-对应UUID>/ - 二级索引的SSTable文件放到对应索引的独立隐藏目录:
/var/lib/cassandra/data/<keyspace_name>/<table_name-对应UUID>/.<index_name>/,严禁将索引文件放到主表根目录
- 主表SSTable文件(数据文件、校验文件、元数据文件等)放到主表对应目录:
- 修正文件属主和权限,确保cassandra运行用户对所有拷贝的文件拥有完整读写权限,避免启动时出现文件访问拒绝问题。
- 启动Cassandra容器:
docker start cassandra - 等待节点完全启动、集群状态恢复正常后,执行refresh命令加载数据:
docker exec cassandra nodetool refresh <keyspace_name> <table_name> - 登录cqlsh校验表数据、验证索引查询逻辑正常,执行
nodetool status、nodetool tpstats确认节点无异常报错即可。
内容的提问来源于stack exchange,提问作者Dark debo
相关产品推荐
相关产品推荐

