2

我有一个 Java Web 应用程序(WAR 部署到 Tomcat),它在内存中保留一个缓存(Map<Long,Widget>)。我有一个包含widgets表的 Postgres 数据库:

widget_id | widget_name | widget_value
(INT)       (VARCHAR 50)  (INT)

Widget为了POJO 和表记录之间的 O/R 映射widgets,我使用的是 MyBatis。我想实现一个解决方案,只要表中的值发生变化,Java 缓存(地图)就会实时更新widgets。我可以有一个轮询组件,例如每 30 秒检查一次表,但轮询在这里感觉不是正确的解决方案。所以这就是我的提议:

  1. 编写一个调用存储过程的 Postgres 触发器 ( run_cache_updater())
  2. 该过程依次运行一个 shell 脚本 ( run_cache_updater.sh)
  3. 脚本 base-64 对更改widgets的记录进行编码,然后将编码的记录卷曲到 HTTP URL
  4. Java WAR 有一个 servlet 侦听 cURLed URL 并处理HttpServletRequests发送给它的任何内容。它使用 base-64 解码记录并以某种方式将其转换为WidgetPOJO。
  5. Map<Long,Widget>使用正确的键/值更新缓存 ( )。

这个解决方案感觉很尴尬,所以我首先想知道那里的任何 Java/Postgres 大师将如何处理这种情况。在这里投票是更好/更简单的选择吗(我只是很固执吗?)我忽略了另一个/更好/更标准的解决方案吗?

如果不是,并且此解决方案是将更改的记录从 Postgres 推送到应用程序层的标准方式,那么我会窒息如何编写触发器、存储过程和 shell 脚本,以便将整个widgets记录传递到 cURL 语句中. 在此先感谢您的任何帮助。

4

1 回答 1

4

我无法与 MyBatis 交谈,但我可以告诉你 PostgreSQL 内置了一个发布/订阅系统,它可以让你用更少的黑客行为来做到这一点。

首先,设置一个触发器widgets,在每个插入、更新和删除操作上运行。让它提取主键和. (嗯,从 PL/pgSQL,你可能想要。)如果事务提交,PostgreSQL 将广播你的通知,使通知和相应的数据更改对其他连接可见。NOTIFYwidgets_changed, idPERFORM pg_notify(...)

在客户端中,您需要运行一个专门用于保持此地图最新的线程。它将连接到 PostgreSQL,开始排队通知,填充地图,并等待通知到达。(检查通知显然涉及轮询 JDBC 驱动程序,这很糟糕,但并不像您想象的那么糟糕。请参阅PgNotificationPoller了解具体实现。)一旦您看到通知,查找指示的记录并更新您的地图。请注意,在初始 之前很重要,因为记录可以在和之间更改。LISTENwidgets_changedSELECT * FROM widgetsLISTENSELECT *SELECT *LISTEN

这种方法不需要 PostgreSQL 了解有关您的应用程序的任何信息。它所要做的就是发送通知;您的应用程序会完成其余的工作。没有 shell 脚本、HTTP 和回调,让您无需重新配置数据库即可重新配置/重新部署应用程序。它只是一个数据库,可以备份、恢复、复制等,没有额外的复杂性。同样,您的应用程序也没有额外的复杂性:它所需要的只是与您已经拥有的 PostgreSQL 的连接。

于 2012-12-04T02:16:33.350 回答