LibreOffice文件保存采用临时文件策略的设计原理是什么?
临时文件替换写入的设计逻辑说明
对400.Oliver.odt执行文件保存操作时,目录监听工具inotifywait输出的事件如下:
./ CREATE lu35285h45cvw.tmp ./ OPEN lu35285h45cvw.tmp ./ CLOSE_WRITE,CLOSE lu35285h45cvw.tmp ./ OPEN lu35285h45cvw.tmp ./ MODIFY lu35285h45cvw.tmp ./ ACCESS lu35285h45cvw.tmp ./ MODIFY lu35285h45cvw.tmp ./ MODIFY lu35285h45cvw.tmp ./ ACCESS lu35285h45cvw.tmp ./ MODIFY lu35285h45cvw.tmp ./ CLOSE_WRITE,CLOSE lu35285h45cvw.tmp ./ MOVED_FROM lu35285h45cvw.tmp ./ MOVED_TO 400.Oliver.odt ./ ATTRIB 400.Oliver.odt ./ ATTRIB 400.Oliver.odt ./ OPEN 400.Oliver.odt ./ CLOSE_WRITE,CLOSE 400.Oliver.odt ./ OPEN 400.Oliver.odt ./ OPEN 400.Oliver.odt ./ ACCESS 400.Oliver.odt ./ ACCESS 400.Oliver.odt ./ CLOSE_NOWRITE,CLOSE 400.Oliver.odt ./ CLOSE_WRITE,CLOSE 400.Oliver.odt
整个流程是先生成随机命名的临时文件,将编辑内容完全写入临时文件后,再通过移动操作替换原odt文件,是文本编辑器、办公软件非常通用的保存实现,遵循的核心编程原则和实践如下:
- 原子性原则:符合ACID特性中的原子性要求,保存操作要么完全成功,用户拿到完整的新文件,要么完全失败,原文件不受影响,不存在半完成的中间状态。
- 容错性设计实践:最大化降低异常场景下的数据丢失风险。
- 幂等性设计原则:就算保存操作被重复触发、意外中断,也不会破坏原有文件的完整性,重复执行也不会出现异常结果。
不直接写入原odt文件的核心原因
- 避免异常导致原文件永久损坏
如果直接修改原文件,写入过程中如果出现程序崩溃、系统断电、磁盘存储空间不足等异常,原文件会停在写入一半的损坏状态,用户的历史数据直接丢失。使用临时文件的话,只有所有内容完全写入临时文件、校验无误之后,才会执行替换操作,就算写入临时文件时出问题,原文件也完好无损。 - 保证文件读取的一致性
重命名/移动操作在绝大多数本地文件系统(ext4、XFS、NTFS等)上都是原子操作,只要替换操作完成,其他进程读取到的要么是完整的旧版本文件,要么是完整的新版本文件,不会读到半写的中间内容,避免其他程序读取该文件时出现解析错误。 - 降低文件锁冲突概率
直接写入原文件时需要长时间持有写锁,会阻塞其他进程对该文件的读取操作。写入临时文件的整个过程都不会操作原文件,原文件可以正常被其他程序读取,只有最后替换的瞬间会有极短的锁占用,对其他进程的影响降到最低。 - 简化异常恢复逻辑
如果写入临时文件过程中出错,只需要直接删除临时文件即可,不需要对原文件做复杂的回滚操作,也不会污染原文件的存储空间。
内容的提问来源于stack exchange,提问作者Stephen Boston
相关产品推荐
相关产品推荐

