数据文件坏了,ZooKeeper 启动时怎么处理?这篇故意制造几种损坏——快照截断、快照清零、快照全丢、日志内容被改、日志尾部撕裂——看它是容错启动、拒绝启动、还是悄悄丢数据。
快照: ['snapshot.253', 'snapshot.331', 'snapshot.534'] 日志: 7 个
[正常] 启动成功,znode 数 1505
截断 snapshot.534:175107 → 87553 字节
[快照截断] 启动成功,znode 数 1505
日志: Invalid snapshot snapshot.534. len = 2021161080, byte = 120[快照 0 字节] 启动成功,znode 数 1505
[无快照(默认)] 启动失败,退出码 1
日志: java.io.IOException: No snapshot found, but there are log entries. Something is broken!
日志: Exiting JVM with code 1
[无快照 + trust.empty=true] 启动成功,znode 数 1505
日志: java.io.IOException: No snapshot found, but there are log entries. Something is broken!
日志: Exiting JVM with code 1
日志: No snapshot found, but there are log entries. This should only be allowed during upgrading.我最先一次手工破坏日志时,在一个很小的日志文件里看到过「Last transaction was partial」加上 9 个 znode 丢失(1505 → 1496)的结果;但后来用更干净的方法重复,同样的「改坏中间字节」得到的是 CRC 失败。能不能稳定复现那种「丢数据但启动成功」的情形,我没有确认,所以不把它当结论。
(a) 破坏 log.523(有效数据约 28688 字节)末尾处偏移 28664 的 16 字节
[(a) 日志尾部损坏] 启动失败,退出码 1
日志: java.io.IOException: CRC check failed
日志: Exiting JVM with code 1
(b) 破坏 log.555(有效数据约 21038 字节)中间偏移 10519 的 16 字节
[(b) 日志中间损坏] 启动失败,退出码 1
日志: java.io.IOException: CRC check failed
日志: Exiting JVM with code 1
(c) 模拟断电造成的「撕裂写」:把 log.562(有效数据约 19049 字节)最后 30 字节清零(最后一条事务只写了一半)
[(c) 最后一条事务写了一半] 启动成功,znode 数 1505
日志: Last transaction was partial.