Cassandra是否支持PITR(时点恢复)?配置后恢复失败求排查
首先明确:Cassandra确实支持基于commit log归档的时点恢复(PITR),但你的配置、脚本和操作流程里有几个关键疏漏,导致恢复没达到预期。下面逐个拆解问题:
一、配置文件的格式错误
你的restore_point_in_time用了2020:12:18 15:24:00的格式,Cassandra要求的标准格式是yyyy-MM-dd HH:mm:ss(注意日期部分用横杠分隔),而且这个时间需要是UTC时间(如果你的服务器时区不是UTC,要做时间转换)。格式不匹配会导致Cassandra无法识别你指定的恢复时点,直接跳过筛选逻辑。
二、归档/恢复脚本的逻辑问题
1. 归档脚本(archive_commit_log.sh)
你现在的脚本是直接复制所有commit log文件,但Cassandra的归档机制是逐个触发已完成的commit log文件归档(比如文件写满、节点正常重启时),会把当前要归档的单个文件路径作为参数传递给脚本。你的脚本没有接收这个参数,会把活跃的commit log也归档,这部分日志包含未完成的事务,会干扰后续恢复。正确的脚本应该是:
#!/bin/bash # $1是Cassandra传递的待归档commit log文件路径 cp "$1" /u01/cassandra/arch/
2. 恢复脚本(move_achive_to_live.sh)
你直接把所有归档日志复制到commitlog目录,但PITR的核心是只重放指定时点之前的commit log。每个commit log文件名包含UTC时间戳(比如CommitLog-1608285840000-1608286020000.log,前半部分是日志创建时间戳),你需要根据这个时间戳和restore_point_in_time对比,只复制符合条件的文件。比如可以用脚本筛选:
#!/bin/bash RESTORE_TIME=$(date -d "2020-12-18 15:24:00" +%s)000 for log in /u01/cassandra/arch/CommitLog-*.log; do # 提取文件名中的起始时间戳 LOG_START=$(echo "$log" | awk -F'-' '{print $2}') if [ "$LOG_START" -le "$RESTORE_TIME" ]; then cp -f "$log" /var/lib/cassandra/commitlog/ fi done
三、操作流程遗漏的关键步骤
PITR是基于快照的增量恢复,你不能直接清空commit log就启动恢复,必须先恢复到某个快照的基础状态:
- 准备基础快照:你需要有一个在
restore_point_in_time之前生成的节点快照(用nodetool snapshot <keyspace>命令生成),这是恢复的基准。 - 停止节点并清理环境:
- 停止Cassandra服务
- 清空
/var/lib/cassandra/data目录(这是当前节点的数据目录) - 清空
/var/lib/cassandra/commitlog目录
- 恢复快照数据:把之前生成的快照文件(默认在
/var/lib/cassandra/data/<keyspace>/<table>/snapshots/<snapshot_name>)复制回对应的data目录下。 - 启动节点并验证:启动Cassandra后,查看
system.log,你应该能看到类似Replaying commit log files...的日志,确认Cassandra在重放符合时点的日志。
最后总结修正步骤
- 修正
commitlog_archiving.properties中的restore_point_in_time格式为2020-12-18 15:24:00(确保是UTC时间) - 替换归档脚本为接收单个文件参数的版本
- 替换恢复脚本为带时间戳筛选的版本
- 恢复指定时点之前的快照到data目录
- 启动Cassandra,观察系统日志确认恢复过程
内容的提问来源于stack exchange,提问作者shanmukha

