向文件追加数据的时候发生断电之类的故障,会怎样? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zzkde
V2EX    问与答

向文件追加数据的时候发生断电之类的故障,会怎样?

  •  1
     
  •   zzkde 2021-03-25 23:39:21 +08:00 1587 次点击
    这是一个创建于 1659 天前的主题,其中的信息可能已经有所发展或是发生改变。

    在写 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 } } 

    etcd 的 wal 源码

    5 条回复    2021-03-26 13:56:48 +08:00
    F281M6Dh8DXpD1g2
        1
    F281M6Dh8DXpD1g2  
       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
    你的实现看起来没啥问题
    wakzz
        2
    wakzz  
       2021-03-26 09:07:10 +08:00
    你这个其实是在问数据落盘的方案,现在的主流方式有:
    1. Double Write
    2. Shadow Paging
    3. Trans Log
    4. 每次全量写(Redis 的 RDB)
    wakzz
        3
    wakzz  
       2021-03-26 09:11:05 +08:00
    程序应该自己保证数据落盘后文件完整性,就算写入中途突然断电中断导致数据页损坏,也可以通过应用本身的逻辑处理,或恢复成正确的旧数据,或接着断电前继续写新数据,而不会出现数据错乱的情况。
    zzkde
        4
    zzkde  
    OP
       2021-03-26 12:50:24 +08:00
    @wakzz Double Write 和 Shadow Paging 关注的是数据页的写入,Trans Log 就是 wal 。无法解决我当前的疑惑啊
    @liprais 赞!这篇文章刚好我也看了,但是里面没有更多的实现细节
    wakzz
        5
    wakzz  
       2021-03-26 13:56:48 +08:00
    @zzkde 常见的是 Trans Log 和 Double Write 组合,数据更新时先添加 Trans Log,如果 Trans Log 写入失败则操作失败,每一条 Trans Log 都有完整校验,应用重启恢复读取 Trans Log 时完整校验没过 的 log 直接忽略。
    然后数据写入通过 Double Write 方式,Double Write 是写两次,如果是第二次写失败可以通过第一次写的数据恢复;如果是第一次写失败,则可以通过 Trans Log 和原本的数据副本恢复。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5671 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 06:30 PVG 14:30 LAX 23:30 JFK 02:30
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86