在并发环境中拍摄复杂可变结构的快照

Xan*_*nth 5 clojure

给定:各种嵌套集合的复杂结构,其中refs分散在不同的级别.

需求:一种获取此类结构快照的方法,同时允许写入在其他线程中继续发生.

因此,"读者"线程需要在单个长事务中读取整个复杂状态."编写者"线程同时在多个短交易中进行修改.据我所知,在这种情况下,STM引擎利用了refs历史.

这里我们有一些有趣的结果.例如,读者在交易开始后10秒内到达一些参考.Writer每1秒修改一次ref.它产生10个ref历史值.如果超过ref的:max-history限制,读者交易将永远运行.如果超过:min-history,则可以多次重新运行事务.

但实际上读者只需要一个ref值(第一个),而作者只需要最近的一个.历史列表中的所有中间值都是无用的.有没有办法避免这种历史过度使用?

谢谢.

jef*_*unt 0

您问题的一般答案是您需要两件事:

  1. 指示系统处于“快照写入”模式的标志
  2. 用于保存系统处于快照模式时发生的所有事务的队列

至于如果由于快照过程不够快而导致队列溢出该怎么办,那么,除了优化该过程或增加队列的大小之外,您无能为力 - 这将是是您必须根据应用程序的需求达到的平衡。这是一个微妙的平衡,并且需要进行一些相当广泛的测试,具体取决于您的系统的复杂程度。

但你走在正确的轨道上。如果您基本上将系统置于“快照写入模式”,那么您的读取器/写入器方法应该自动更改它们读取/写入的位置,以便进行更改的线程获取所有“当前值”并且读取该值的线程快照状态正在读取所有“快照值”。您可以将它们分成单独的方法 - 快照读取器将使用“快照值”方法,而所有其他线程将读取“当前值”方法。

当快照读取器完成工作后,它需要清除快照状态。

如果线程在当前未设置“快照状态”时尝试读取“快照值”,则它们应该简单地以“当前值”进行响应。没什么大不了的。

允许为备份目的拍摄文件系统快照,同时不阻止写入新数据的系统遵循类似的方案。

最后,除非您需要保留对系统的所有更改的记录(即用于审计跟踪),否则事务队列实际上不需要是要应用的更改队列 - 它只需要存储最新的您在系统中更改的任何内容的值。当“快照状态”被清除时,您只需将所有这些未提交的值写入系统,然后称之为完成。您可能需要考虑的是记录尚未进行的更改,以防您需要从崩溃中恢复,并仍然应用这些更改。日志文件将为您提供所发生情况的记录,并可以让您进行此恢复。这是对恢复过程的过度简化,但这并不是您真正的问题,所以我就到此为止。