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

时间:2010-12-23 22:06:34

标签: clojure stm

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

4 个答案:

答案 0 :(得分: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

答案 1 :(得分:3)

您可能对以下内容感兴趣:

  1. Alyssa Kwan的修改后的Clojure核心为refs增加了持久性,请参阅: ANN: Durable refs with ACID guarantees - Phase IANN: Durable Clojure - Phase II - Persistent Data StructuresANN: Durable Clojure - Functions and Closures

  2. Sergey Didenko的图书馆,它不具备强大的耐久性保证,但与此非常接近: Simple-Persistence-for-Clojure

  3. 对于程序员来说,其他方法可能不那么透明。

答案 2 :(得分:2)

STM模型非常适合在系统发生变化时跟踪对系统的多次访问。它不太直接适用于数据持久性,其中更改需要在访问它们的线程的生命周期之外可访问。

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

答案 3 :(得分:1)

如果你想要一个具有快速内存访问权限并且不时在幕后持续存在的数据库,那么使用真正的数据存储,而不是尝试构建自己的数据存储,这将是一项相当大的工作。 / p>

RedisMongoDB是两个不错的选择,但还有很多其他选项。您可以分别在https://github.com/ragnard/redis-clojurehttps://github.com/somnium/congomongo找到Redis和Mongo的Clojure库。