2

我在 Go 中有一个小项目,它通过 tcp 接收文本行以进行处理。但是,为了确保稳健性,我想创建某种日志,以便在电源故障的情况下不会丢失任何内容(例如,我的应用程序接收到一帧数据,但尚未处理)。

我已经在 Google 上搜索了有关如何实现日志文件的任何指南,但是搜索结果受到 Oracle RDBMS 文档等的严重污染。

我的想法是这样的:收到一行后立即将其写入带有“未处理标志”的文件。处理后,更新文件以清除此标志,打开覆盖。在清除该标志的同时,向数据发送方发送一个“已处理的确认”。在日志中处理固定大小的“插槽”也许是最简单的方法,以确保我可以重用已释放的插槽,而不是拥有一个不断增加的文件并维护未使用插槽的“空闲列表”。

在自定义代码中实现此类文件是否有任何“最佳实践”,关于文件结构、填充和锁定的 ige?在 Go 中这样做是否有任何顾虑,因为它是跨平台的,而不是使用本机文件系统 API?

4

1 回答 1

5

你不应该重写日记。只需将操作附加到它,以便您可以重新创建它们,然后控制您想要的严格级别。

逻辑应该很简单:

  1. 接收消息

  2. 写日记

  3. 现在可以选择在日志上执行 fsync - 取决于您的一致性要求。

  4. 可选然后发送“收到的确认” - 取决于您的需要。

  5. 处理消息。

  6. 可选地将另一个“已处理”记录写入具有记录 ID 的文件。你并不总是需要它,但你不会重写旧记录。或者,您可以使用已处理的“顶级事务 id”编写一个单独的文件,这样您将自动知道在发生故障时从哪里开始再次处理。这将减少期刊的大小。

  7. 发送“已处理的确认”或“处理失败” - 再次取决于您想要什么。

数据库通常让您控制 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 中的普通文件编写器在幕后做了多少缓存,如果你打算使用它,我建议你阅读代码。

于 2014-05-08T10:18:42.913 回答