我该如何让Clojure STM程序持久化?

17

我正在编写一个使用STM的Clojure程序。目前,我正在从数据库中启动populating STM(使用refs),然后在每次dosync事务成功时异步更新数据库。但是,我不知道这样做是否正确,或者是否有更好的标准技术来完成这项任务。有人可以解释一下如何将STM的ACI属性转换为Clojure程序中的ACID吗?

4个回答

13
一般来说,将ACID的“D”添加到任何程序中都不是微不足道的,这取决于程序的要求。在实现之前需要确定一个重要的规范。
问题主体显示,您的程序似乎只在启动时读取并在STM更改后写入,数据库会滞后于STM中的值一小段时间。但是,如果包括其他程序在内的其他实例访问数据库,则需要使用锁定,在事务之前锁定对数据库的访问,并在写入数据库后解锁(顺便提一下,您的情况中数据库可以是任何东西,包括文件系统中的简单文件)。当存在多个读写时,两者都涉及数据库,无法避免此问题。
如果没有多次访问,则异步写入是可以的,因为您的程序在访问方面是单线程的,代码保证始终按顺序运行。
如果只有多个写线程和在启动后没有读取且只有单个实例,则只需确保正确的写入顺序。您可以使用代理完成此操作,其中代理基本上是写入到数据库的操作队列。您将dosync包装在参考事务和代理周围,这样除了持久性外,还可以获得耐久性。
一般来说,涉及副作用的要求越复杂,为确保ACID所需的技巧就越多。如果您有其他要求,则我给出的实现可能需要更改。
编辑:
(def db-agent (agent dummy-value))
(defn db-write [_ data] ;; make this intelligent to handle when db is not up
    (try
        (write-to-db data)
    (catch ... database fails, do a retry or let user know of problem))
    _)
;; in the transaction code
(dosync
    (alter my-ref ...)
    (send-off db-agent db-write @my-ref)) ;; ensure db gets written to

啊,终于有人试图回答实际问题了,谢谢 :) 数据库(H2或Oracle)没有多进程访问。唯一访问数据库的进程是Clojure程序本身。 - yazzapps.com
你的程序具有多线程读取还是多线程写入?如果是多线程读取,是否在启动后一直存在? - bmillare
启动后,是从持久存储还是从内存引用进行多线程读取? - bmillare
好的,那么我建议使用代理应该就足够了,我会编辑帖子以反映一些代码。 - bmillare
谢谢,代理是一种有用的节省方式,确保写入是串行的吧? - yazzapps.com
是的,为了保留写入顺序,也就是序列化。 - bmillare

3

FleetDB的链接指向了一篇关于葡萄酒的博客。 - Petrus Theron

2

STM模型非常适合跟踪多个系统的访问,因为它们发生变化。但是,它不太适用于数据持久性,因为这些更改需要在访问它们的线程的生命周期之外进行访问。

通常最好将ACID中的'D'与STM分开考虑。


1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接