在本地连续持久化时间,用于超时的灾难恢复



我正在编写一个Go应用程序,在内存中调度超时(使用time.Timer)。如果应用程序崩溃或重新启动,应用程序能够重新加载从重新启动开始的超时(多亏了DB记录),这意味着如果在崩溃和应用程序备份之间应该触发一个超时,它将被错过。

理想情况下,在停机期间应该发生的所有超时都应该仍然触发(有延迟,但总比错过要好)。我的想法是让应用程序在运行时每秒将当前时间戳写入一个文件(或SQLiteDB)。当应用程序重新启动时,它可以查看最新的时间戳,并立即触发该时间戳和现在之间的所有超时(并将其他超时安排到将来)。

这种方法有意义吗?它有缺陷吗?这个模式有名字吗?

您正在描述分布式计算设置。

当某个合作伙伴给你发送"开始"时;事件,他们可能应该等待你的"回复"。之前任何冒险的事情。否则他们不会知道你(a)听到并(b)记录了事件。也就是说,缺乏承认会招致失败比赛和丢失的事件当主机可能随机重新启动。

理想情况下,合作伙伴将这些事件持久化到稳定自己的储存,开始之前昂贵的操作。

考虑到显然没有ack,听起来比如你的应用需要在可行的情况下尽快持久化事件,要么通过局域网连接到冗余主机,要么连接到文件系统。一个简单的方法是

  • 接收合作伙伴的消息
  • write()一行,附加到文本文件
  • fsync()从内存刷新到磁盘/NVRAM/SSD

当您收到"完成"时;事件和时间执行"terminate"命令,也记录它们。不需要立即同步。可能是其他事件经常来一次,他们就会把所有东西都冲干净挂起的日志记录很快就会输出到磁盘。

重新启动时,只需查找到文件的末尾回放所有记录的事件,设置一堆超时计数器,并在日志记录时取消它们表明他们已经完成了。有些超时可能会触发我们读完日志后,因为它们不新鲜。假定它对……无害为任务发出terminate(task_id)命令已经正常退出了


另一种策略,它不那么依赖对准确的日志记录,是对所有状态的查询当前正在运行的作业。在稍远的地方设置一个保守超时未来,希望你能熬夜看到这样的时间到了。

或者使用额外的信息,比如每个任务的Size和start_time,以选择更合理的超时值。


考虑使用kafka, redis或类似的分布式消息代理来协调群集的操作;而不是依赖于文件系统或RDBMS。有一些低延迟的解决方案很好地平衡一致性,可用性和分区容忍度。

最新更新