Postgres触发更新Java缓存

时间:2012-12-04 01:32:51

标签: java postgresql stored-procedures curl triggers

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

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

要在Widget POJO和widgets表记录之间进行O / R映射,我使用的是MyBatis。我想实现一个解决方案,只要widgets表中的值发生变化,Java缓存(Map)就会实时更新。我可能有一个轮询组件,每隔30秒检查一次表,但轮询只是不适合这里的解决方案。所以这就是我的建议:

  1. 编写调用存储过程(run_cache_updater()
  2. 的Postgres触发器
  3. 该过程依次运行shell脚本(run_cache_updater.sh
  4. 脚本base-64对已更改的widgets记录进行编码,然后将编码记录cURL为HTTP URL
  5. Java WAR有一个servlet侦听cURLed URL并处理发送给它的任何HttpServletRequests。它base-64解码记录并以某种方式将其转换为Widget POJO。
  6. 使用正确的键/值更新缓存(Map<Long,Widget>)。
  7. 这个解决方案感觉很尴尬,所以我首先想知道那里的Java / Postgres大师会如何处理这种情况。在这里轮询更好/更简单的选择(我只是顽固吗?)我还有其他/更好/更标准的解决方案吗?

    如果没有,并且此解决方案是将已更改的记录从Postgres推送到应用程序层的标准方法,那么我就会扼杀如何编写触发器,存储过程和shell脚本以便整个{{1} } record被传递到cURL语句中。在此提前感谢您的任何帮助。

1 个答案:

答案 0 :(得分:3)

我不能和MyBatis说话,但我可以告诉你PostgreSQL有一个发布/订阅系统,这样可以让你以更少的hackery做到这一点。

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

在客户端中,您需要运行专用于使此映射保持最新的线程。它将连接到PostgreSQL,LISTEN widgets_changed以开始排队通知,SELECT * FROM widgets来填充地图,并等待通知到达。 (显然检查通知involves polling the JDBC driver,这很糟糕,但没有您想象的那么糟糕。请参阅PgNotificationPoller了解具体实现。)一旦看到通知,请查看指示的记录并更新地图。请注意,在LISTEN之前SELECT *非常重要,因为记录可以在SELECT *LISTEN之间更改。

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