使用数据库的单例应用程序进程的模式

时间:2011-12-29 04:03:32

标签: postgresql

我有一个后端进程,用于维护PostgreSQL数据库中的状态,该数据库需要对前端可见。我想:

  • 正确处理后端停止并启动。仅这一点就像在启动时清除后端状态表一样简单。

  • 防止后端的多个实例相互踩踏。应该只有一个后端进程,但如果我不小心启动了第二个实例,我想确保第一个实例被终止,或者第二个实例被阻塞,直到第一个实例终止。

我能想到的解决方案包括:

  • 利用我的后端进程侦听端口的事实。如果进程的第二个实例尝试启动,它将失败并显示“Address in in use”。我必须确保在连接到数据库和擦除状态表之前执行listen步骤。

  • 打开辅助连接并运行以下命令:

    BEGIN;
    LOCK TABLE initech.backend_lock IN EXCLUSIVE MODE;
    

    注意:IN EXCLUSIVE MODE的原因是LOCK默认为AccessExclusive锁定模式。这与pg_dump获取的AccessShare锁相冲突。

    不要提交。将表保持锁定直到程序死亡。

维护一个在PostgreSQL数据库中维护状态的单例后端进程有什么好的模式?理想情况下,我会在连接期间获得锁定,但LOCK TABLE不能在事务之外使用。

背景

考虑具有“代理”进程的应用程序,该进程与数据库通信,并接受来自客户端的连接。每次客户端连接时,代理进程都会向数据库添加一个条目。这有两个好处:

  • 前端可以查询数据库以查看连接的客户端。

  • 当另一个名为initech.objects的表中的行发生更改,并且客户端需要了解它时,我可以创建一个触发器来生成客户端列表以通知更改,将其写入表中,然后使用NOTIFY唤醒经纪人流程。

    如果没有连接客户端表,应用程序必须确定要通知的客户端。在我的情况下,这变得非常混乱:在内存中存储initech.objects表的副本,并且每当行更改时,将旧行和新行分派给处理程序,以检查行是否已更改并执行如果有的话。要有效地做到这一点,需要针对存储在内存中的表和对行更改感兴趣的处理程序创建“索引”。我在代理程序中编写了SQL的索引和查询功能的复制品。我宁愿把这项工作转移到数据库。

总之,我希望代理进程在数据库中维护其某些状态。它极大地简化了对客户端的配置更改调度,但它要求一次只将一个代理实例连接到数据库。

2 个答案:

答案 0 :(得分:2)

答案 1 :(得分:0)

我今天以一种我认为简洁的方式解决了这个问题:

CREATE TYPE mutex as ENUM ('active');
CREATE TABLE singleton (status mutex DEFAULT 'active' NOT NULL UNIQUE);

然后你的后端程序试图这样做:

insert into singleton values ('active');

如果不这样做,则退出或等待。

相关问题