如何使clojure STM程序持久化?

如何使clojure STM程序持久化?,clojure,stm,Clojure,Stm,我正在编写一个使用STM的clojure程序。目前,我正在从数据库启动时填充STM(使用REF),然后在dosync事务成功时异步更新数据库。我不知道我是否用正确的方法来做这件事,或者是否有更好的标准技术来做这件事。有谁能向我解释一下他们是如何在Clojure程序中将STM的ACI属性转换成ACID的吗?STM模型非常适合跟踪系统变化时的多址访问。它不太直接适用于数据持久性,在这种情况下,更改需要在访问它们的线程的生命周期之外才可访问 通常,最好将ACID中的“D”与STM分开考虑。一般来说,将

我正在编写一个使用STM的clojure程序。目前,我正在从数据库启动时填充STM(使用REF),然后在dosync事务成功时异步更新数据库。我不知道我是否用正确的方法来做这件事,或者是否有更好的标准技术来做这件事。有谁能向我解释一下他们是如何在Clojure程序中将STM的ACI属性转换成ACID的吗?

STM模型非常适合跟踪系统变化时的多址访问。它不太直接适用于数据持久性,在这种情况下,更改需要在访问它们的线程的生命周期之外才可访问


通常,最好将ACID中的“D”与STM分开考虑。一般来说,将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

如果您想要一个具有快速内存访问能力的数据库,并且可以不时地在后台持久化,那么请使用真正的数据存储,而不是尝试构建自己的数据库,这将是一项相当大的工作


和是两个不错的选择,但还有很多其他选择。您可以分别在Redis和Mongo的和中找到Clojure库。

您可能会感兴趣:

  • Alyssa Kwan改进的Clojure core为REF添加了持久性,请参见: ,

  • 谢尔盖·迪登科(Sergey Didenko)的图书馆没有提供很强的耐久性保证,但非常接近:


  • 其他方法对程序员来说可能不那么透明。

    啊,最后有人试图回答实际问题,谢谢:)没有对数据库的多进程访问(H2或Oracle)。访问数据库的唯一进程是Clojure程序本身。您的程序是多线程读取还是多线程写入?如果是多线程读取,是在启动后进行的吗?启动后,是从持久存储中读取多线程,还是从内存引用中读取多线程?好的,那么我建议使用代理就足够了,我将编辑帖子以反映一些代码。谢谢,这是使用代理保存的有用方法,确保文章是连续的,我想?FleetDB链接到一个关于葡萄酒的博客。