我在Go中有一个小项目正在通过tcp接收文本行来处理。但是,为了确保稳健性,我想创建某种日志,以便在电源出现故障时不会丢失任何内容(例如,我的应用程序收到了一帧数据,但尚未处理)。
我已经搜索了有关如何实施日志文件的任何指南,但搜索结果受到Oracle RDBMS文档等严重污染。
我的看法是这样的:收到一行后立即将其写入带有"未处理标志的文件"。处理完毕后,更新文件以清除此标志,打开覆盖。在清除此标志的同时,发送一个"处理过的ack"到数据发送者。也许最容易处理固定大小的插槽"在日志中,以确保我可以重用已释放的插槽,而不是拥有一个不断增加的文件,并维护一个免费列表"未使用的插槽。
是否有任何"最佳做法"用于在自定义代码中实现这样的文件,例如文件结构,填充和锁定?在Go中是否存在任何问题,因为它是跨平台的,而不是使用本机文件系统API?
答案 0 :(得分:5)
你不应该改写日记。只需将操作附加到它,以便您可以重新创建它们,然后控制所需的严格级别。
逻辑应该只是:
收到消息
将其写入期刊
现在可选择在期刊上执行fsync - 具体取决于您的一致性要求。
可选择然后发送"收到的确认" - 取决于您的需求。
处理邮件。
可选择写另一个"已处理"记录到具有记录ID的文件。你并不总是需要那个但是你不会重写旧记录。或者,您可以使用" top transaction id"写一个单独的文件。您已经处理完毕,因此如果发生故障,您将自动知道再次开始处理的位置。这将减少期刊的大小。
发送"已处理的确认"或者"处理失败" - 再次,取决于你想要什么。
数据库通常可以控制fsync行为 - 每次写入时,每隔N秒,当操作系统决定时 - 它是速度与耐用性的关系。
关于这个主题的好读物可能是关于redis持久性的这篇文章: http://oldblog.antirez.com/post/redis-persistence-demystified.html
[编辑]关于这个主题的另一篇精彩读物 - http://engineering.linkedin.com/distributed-systems/log-what-every-software-engineer-should-know-about-real-time-datas-unifying
至于它的Go方面 - 有一些写入文件的选项,从低级文件处理程序到缓冲式写入程序。当然,文件处理程序可以让您最大程度地控制引擎盖下的内容。我不确定Go中的普通文件编写器幕后有多少缓存,如果您打算使用它,我建议您阅读代码。