Шаблон для однопользовательского процесса приложения с использованием базы данных
1 Joey Adams [2011-12-29 07:03:00]
У меня есть бэкэнд-процесс, который поддерживает состояние в базе данных PostgreSQL, которое должно быть видимым для интерфейса. Я хочу:
-
Правильно обрабатывайте бэкэнд, который остановлен и запущен. Это само по себе так же просто, как очистка таблиц состояния бэкэнда при запуске.
-
Охрана от нескольких экземпляров бэкэнда, попирающих друг друга. Там должен быть только один бэкэнд-процесс, но если я случайно запускаю второй экземпляр, я хочу убедиться, что либо первый экземпляр убит, либо второй экземпляр заблокирован, пока первый экземпляр не умрет.
Решения, о которых я могу думать, включают:
-
Используйте тот факт, что мой серверный процесс прослушивает порт. Если второй экземпляр процесса пытается начать, он не сработает с "Адресом, который уже используется". Я просто должен убедиться, что он выполняет шаг
listenперед подключением к базе данных и уничтожением таблиц состояний. -
Откройте дополнительное соединение и выполните следующее:
BEGIN; LOCK TABLE initech.backend_lock IN EXCLUSIVE MODE;Примечание. Причина
IN EXCLUSIVE MODEзаключается в том, чтоLOCKумолчанию установлен в режим блокировки AccessExclusive.Это конфликтует с блокировкой AccessShare, полученнойpg_dump.Не совершайте. Оставьте таблицу заблокированной до тех пор, пока программа не умрет.
Какая хорошая модель для поддержки одного backend-процесса, поддерживающего состояние в базе данных PostgreSQL? В идеале я бы приобрел блокировку на время соединения, но LOCK TABLE не может использоваться за пределами транзакции.
Задний план
Рассмотрите приложение с "брокерским" процессом, который ведет переговоры с базой данных и принимает подключения от клиентов. Каждый раз, когда клиент подключается, процесс брокера добавляет запись для него в базу данных. Это дает два преимущества:
-
Интерфейс может запрашивать базу данных, чтобы узнать, какие клиенты подключены.
-
Когда строка изменяется в другой таблице с именем
initech.objects, и клиенты должны знать об этом, я могу создать триггер, который генерирует список клиентов, чтобы уведомлять об изменении, записывать его в таблицу, а затем использовать NOTIFY для пробуждения брокерский процесс.Без таблицы подключенных клиентов приложение должно выяснить, какие клиенты уведомлять. В моем случае это оказалось довольно запутанным: сохраните копию таблицы
initech.objectsв памяти, и в любой момент, когда строка изменится,initech.objectsстарые строки и новую строку обработчикам, которые проверяют, изменилась ли строка и действовала ли она сделал. Для этого эффективно создавать "индексы" как для хранимой таблицы, так и для обработчиков, заинтересованных в изменениях строк. Я делаю плохую копию SQL-индексирования и запросов в программе брокера. Я предпочел бы переместить эту работу в базу данных.
В заключение я хочу, чтобы брокерский процесс поддерживал некоторые из его состояний в базе данных. Это значительно упрощает отправку изменений конфигурации клиентам, но для этого требуется одновременное подключение только одного экземпляра брокера к базе данных.
postgresql
2 ответа
2 Решение Pavel Stehule [2011-12-29 16:18:00]
это можно сделать с помощью консультативных замков
http://www.postgresql.org/docs/9.1/interactive/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS
0 user2409824 [2014-05-13 18:34:00]
Я решил это сегодня так, как я думал, был кратким:
CREATE TYPE mutex as ENUM ('active');
CREATE TABLE singleton (status mutex DEFAULT 'active' NOT NULL UNIQUE);
Затем ваш внутренний процесс пытается это сделать:
insert into singleton values ('active');
И завершает работу или ждет, если это не удастся.