在写 wal 的实现的时候,不知道如何处理 append 数据时如果发生断电之类的故障如何保证数据安全,想知道如果发生这样的情况会是怎样的,可能是数据只写了一半?也不知道新写入数据时发生故障是否会影响之前写入的内容。我现在的实现是每个 LogEntry 加个 crc 校验字段,在读取数据时检验一下数据时用 crc 校验一下数据。
看了 etcd 的 wal 实现,好像如果发生这样的情况,扇区的情况是全 zero 。
大概流程就是校验一下 crc,不对就进入 isTornEntry 逻辑判断数据所在的扇区是否存在全 zero 的情况。
if err := rec.Validate(d.crc.Sum32()); err != nil {
if d.isTornEntry(data) {
return io.ErrUnexpectedEOF
}
return err
}
isTornEntry 函数的主要逻辑
// if any data for a sector chunk is all 0, it's a torn write
for _, sect := range chunks {
isZero := true
for _, v := range sect {
if v != 0 {
isZero = false
break
}
}
if isZero {
return true
}
}
1
liprais 2021-03-26 00:06:36 +08:00
"The other consideration is to make sure that corrupted log files are detected while reading the log. To handle this, log entries are generally written with the CRC records, which then can be validated when the files are read. "
https://martinfowler.com/articles/patterns-of-distributed-systems/wal.html 你的实现看起来没啥问题 |
2
wakzz 2021-03-26 09:07:10 +08:00
你这个其实是在问数据落盘的方案,现在的主流方式有:
1. Double Write 2. Shadow Paging 3. Trans Log 4. 每次全量写(Redis 的 RDB) |
3
wakzz 2021-03-26 09:11:05 +08:00
程序应该自己保证数据落盘后文件完整性,就算写入中途突然断电中断导致数据页损坏,也可以通过应用本身的逻辑处理,或恢复成正确的旧数据,或接着断电前继续写新数据,而不会出现数据错乱的情况。
|
4
zzkde OP |