Как сделать программу STM clojure постоянной? - PullRequest
17 голосов
/ 24 декабря 2010

Я пишу программу clojure, которая использует STM. В данный момент я заполняю STM (используя refs) при запуске из базы данных, а затем асинхронно обновляю базу данных при каждой успешной транзакции dosync. Я понятия не имею, правильно ли я делаю это, или есть лучший метод для этого. Может ли кто-нибудь объяснить мне, как они превращают свойства ACI STM в ACID в своих программах Clojure?

Ответы [ 4 ]

13 голосов
/ 29 декабря 2010

Как правило, добавление 'D' в ACID к любой программе не является тривиальным и зависит от требований программы. Существует одна важная спецификация, которую необходимо определить, прежде чем можно будет определить реализацию.

Существует ли многопоточный / многопроцессорный доступ к базе данных?

Из текста вопроса ваша программа, по-видимому, читает только при запуске и записывает после изменения в STM, когда база данных отстает от значений в STM на некоторое небольшое количество времени. Однако если к базе данных обращаются другие программы , включая другие экземпляры вашей программы, вам нужно будет использовать блокировки, когда вы блокируете доступ к базе данных непосредственно перед транзакциями, и разблокировать после записи в базу данных (в качестве примечания обратите внимание, что база данных в вашем случае может быть чем угодно, включая простой файл в файловой системе). Это невозможно, если у вас есть несколько операций чтения и записи, потому что они оба являются побочными эффектами, связанными с базой данных.

Если нет множественного доступа , то асинхронная запись хороша, потому что код гарантированно всегда будет работать в порядке, так как ваша программа однопоточна, когда приходит доступ.

Если у вас есть только несколько потоков записи и нет чтения после запуска только с одним экземпляром , то вам нужно только обеспечить правильный порядок записи. Вы можете сделать это с агентами, где агент в основном представляет собой очередь операций записи в базу данных. Вы оборачиваете dosync по ссылочным транзакциям и агенту, обеспечивая вам долговечность в дополнение к постоянству.

Как правило, чем сложнее требования, связанные с побочными эффектами, тем больше уловок вам придется делать для обеспечения ACID. Если у вас есть дополнительные требования, то приведенные мною реализации могут измениться.

EDIT:

(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
3 голосов
/ 31 декабря 2010

Вас может заинтересовать:

  1. Модифицированное ядро ​​Clojure от Алиссы Кван, которое добавляет стойкости к ссылкам, см .: ANN: надежные ссылки с гарантиями ACID - Фаза I , ANN: долговременное замыкание - фаза II - постоянные структуры данных , ANN: долговременное замыкание - функции и замыкания

  2. Библиотека Сергея Диденко, которая не дает надежной гарантии долговечности, но довольно близка к этому: Simple-Постоянство-для-Clojure

Другие подходы могут быть не столь прозрачны для программиста.

2 голосов
/ 24 декабря 2010

Модель STM очень хорошо подходит для отслеживания множественного доступа к системам по мере их изменения.Он менее подходит для сохранения данных, когда изменения должны быть доступны после истечения срока действия потоков, которые к ним обращаются.

Обычно хорошо думать о букве D в ACID отдельно от STM

1 голос
/ 29 декабря 2010

Если вам нужна база данных, которая имеет быстрый доступ в память и время от времени хранится за кулисами, тогда используйте реальное хранилище данных, а не пытайтесь создать свою собственную, что было бы довольно большой работой.

Redis и MongoDB - два хороших варианта, но есть много других. Библиотеки Clojure можно найти в https://github.com/ragnard/redis-clojure и https://github.com/somnium/congomongo для Redis и Mongo соответственно.

...