【问题标题】:PostgreSQL and JMS (Or other Pub-Sub/Callback Mechanism)PostgreSQL 和 JMS(或其他 Pub-Sub/Callback 机制)
【发布时间】:2010-12-18 18:51:33
【问题描述】:

我想让我的 PostgreSQL 服务器在数据发生变化时发送通知,最好是通过 JMS,但还要考虑任何其他 Pub-Sub 机制或回调。

如果可能的话,有什么想法吗?

是否有任何可用的 Java 附加包可以复制此类功能?

【问题讨论】:

    标签: java database postgresql jms publishing


    【解决方案1】:

    编辑:我被告知 PostgreSQL确实支持 Java 中的存储过程。这意味着以下方法变得可行:

    基本上,我会采取的方法是在您想要观看的任何内容上放置一个触发器,然后从中调用一个存储过程。然后存储过程需要与数据库服务器外部的世界进行通信;我曾经在 Java 中做过这样的 SP,它打开了一个套接字连接到同一服务器上侦听端口的进程。如果最坏的情况发生,您可能会编写一个文件并让 imon 之类的东西监视该文件,或者您可以在自己的 exec() shell 中启动一个程序......类似的东西。

    【讨论】:

    • PostgreSQL 确实提供了 Java 存储过程。 “PostgreSQL 以十几种编程语言运行存储过程,包括 Java、Perl、Python、Ruby、Tcl、C/C++,以及它自己的 PL/pgSQL,类似于 Oracle 的 PL/SQL。” - postgresql.org/about
    • 嗯,第一句话是由“据我所知”限定的。无论如何,其余的都是有用的信息。我现在要更新我的答案以反映更大的真相。
    • @TM:根据您的 cmets 给某人一点时间来纠正他们的答案是一种礼貌。我们不可能一直都是 100% 正确的。
    【解决方案2】:

    最简单的方法是使用LISTEN/NOTIFY接口,编写自己的程序来连接数据库,发出一些LISTEN,并在收到通知时做任何你想做的事情——例如通过JMS感知信息,或者简单地做应该做的事,不增加额外的传输层。

    【讨论】:

    • 嗯。如前所述,我不是 Postgres 专家,我很乐意发现一些很酷的新功能。但是,这里:jdbc.postgresql.org/documentation/83/listennotify.html> 他们说:“JDBC 驱动程序的一个关键限制是它不能接收异步通知,并且必须轮询后端以检查是否发出了任何通知。”投票会很糟糕。
    • 您可以使用 pgjdbc-ng 驱动程序进行异步通知github.com/impossibl/pgjdbc-ng
    【解决方案3】:

    如果 LISTEN/NOTIFY 无法通过 JDBC 访问,也许您可​​以通过 LOCK 语句或简单的“SELECT ... FOR UPDATE”和“SELECT ... FOR SHARE”或来自交易中的其他类似查询,这些查询会导致其他交易阻塞。

    消息编写方可以例如启动事务,执行“SELECT ... FOR UPDATE”,等待(Java 代码)直到发生某些变化或计时器到期(例如 30 秒左右),更新锁定的行以指示数据(其他地方?)是否在可用并提交事务以解锁其他人。然后立即使用“SELECT ... FOR UPDATE”重复一个新事务。

    消息阅读方将执行“SELECT ... FOR SHARE”,这将在其他地方启动的“SELECT ... FOR UPDATE”处于活动状态时阻塞。当消息写入方的事务结束时,它会返回消息可用性或消息数据本身的指示。

    希望 PostgreSQL 公平地将各方排队,这样就不会有活锁持续阻塞消息阅读方的风险。

    【讨论】:

      【解决方案4】:

      我会将PL/Java 安装到 Postgres 并为您感兴趣的数据编写一个基于存储过程的触发器,然后在被调用时调用 JMS。 PL/Java 文档很好地涵盖了触发器 + 存储过程部分。

      我没有使用触发代码中的 JMS,但我很确定它没有理由不可行,因为这是标准 Java 代码,而且我对文档的快速复查也没有t 表示任何可疑之处。

      另一种可能性是通过代理服务调用 JMS,使用 perl、python 或任何其他可用于 postgres 存储过程开发的语言。就像 JMS 没有标准的有线协议一样,您必须编写一个代理服务来进行翻译。

      【讨论】:

        【解决方案5】:

        您当然可以创建 Java 语言存储过程并将其放入 PostgreSQL。但是,在您知道自己的消息传递方案完美运行之前,为什么不让它保持简单和可调试呢?如果我这样做(我实际上是在做类似的事情),我会这样做。

        (1) 创建一个“出站消息”表,其中包含有效负载列和 JMS 消息的其他信息。我会在每一行中放置一个时间戳列。

        (2) 为要生成消息的每个项目编写一个数据库触发器。让触发器在“出站消息”表中插入一行。

        (3) 单元测试 (1) 和 (2) 在您更改数据库中应该生成消息的内容时查看出站消息表的内容。

        (4) 自己编写一个简单但高性能的 Java JDBC 客户端程序,它将查询这个出站消息表,为每一行发送一条 JMS 消息,然后删除它。按时间戳对查询中的行进行排序以保留消息顺序。要获得高性能,您需要做好 PreparedStatement 对象和堆管理的其他方面的工作。

        (5) 单元测试 (4) 在您的数据库发生消息生成更改时运行几次。

        (6) 将此程序设置为每分钟重复操作 (6) 几次,同时使用单个持久 JDBC 连接。对小表或空表的查询不是很昂贵,因此这不会破坏您的表服务器。

        (7) 系统测试整个设置。

        (8) 弄清楚如何从 crontab 或启动脚本启动 Java 程序。

        当您完成所有这些工作时,您将拥有一个功能正常的消息传递/通知系统,可以进行系统集成。更重要的是,您将确切地知道您希望 Java 消息发起软件做什么。一旦您启动并运行,如果您的消息延迟或数据库开销被证明是一个大问题,那么您可以将您的 Java 程序迁移到存储过程中。

        另请注意,Apache ActiveMQ 包中内置了 PERL 和其他语言的消息来源绑定,因此您可以选择如何实现消息来源代理。

        这种方法恰好有两个优点:您不会严重依赖 postgreSQL 独特的存储过程方案,并且您不会将具有外部通信依赖关系的代码放入表服务器中。

        祝你好运。

        【讨论】:

          猜你喜欢
          • 2014-07-06
          • 1970-01-01
          • 2021-07-09
          • 2022-01-13
          • 1970-01-01
          • 2017-12-07
          • 1970-01-01
          • 2021-06-29
          • 2011-10-17
          相关资源
          最近更新 更多