我应该如何使一个clojure STM程序持久化?

Zub*_*air 17 clojure stm

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

bmi*_*are 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
Run Code Online (Sandbox Code Playgroud)