2012-12-04 38 views
2

我有一個Java web應用程序(部署到Tomcat的WAR),用於在內存中保存緩存(Map<Long,Widget>)。我有一個包含widgets表Postgres數據庫:Postgres觸發器更新Java緩存

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

爲O/R Widget POJO和widgets表記錄之間的映射,我使用MyBatis的。我希望實現一個解決方案,即只要widgets表中的值發生更改,Java緩存(地圖)就會實時更新。我可能有一個輪詢組件,每隔30秒檢查一次表,但輪詢只是覺得這裏不是正確的解決方案。因此,這裏就是我提議:

  1. 寫Postgres的觸發器調用存儲過程(run_cache_updater()
  2. 在轉彎的過程中運行一個shell腳本(run_cache_updater.sh
  3. 腳本基礎-64編碼更改了widgets記錄,然後將編碼的記錄捲曲到HTTP URL
  4. Java WAR有一個servlet監聽cURLed URL並處理髮送給它的任何HttpServletRequests。它base-64解碼記錄並以某種方式將其轉換成POJO Widget
  5. 使用正確的鍵/值更新緩存(Map<Long,Widget>)。

該解決方案感覺不方便,所以我想首先任何Java/Postgres的大師們如何有會處理這樣的情況。在這裏投票選擇更好/更簡單的選擇(我只是固執?)有沒有另一種/更好/更標準的解決方案,我忽略了?

如果沒有,並且此解決方案是將已更改的記錄從Postgres推送到應用程序層的標準方式,那麼我窒息瞭如何編寫觸發器,存儲過程和shell腳本,以便整個widgets記錄獲取傳入cURL聲明。在此先感謝您的幫助。

回答

3

我不能對MyBatis說話,但我可以告訴你PostgreSQL有一個發佈/訂閱系統,它可以讓你用少得多的hackery來做到這一點。

首先,在每個插入,更新和刪除操作上運行的widgets上設置一個觸發器。讓它提取主鍵和NOTIFYwidgets_changed, id。 (好吧,從PL/pgSQL中,你可能會想要PERFORM pg_notify(...)。)如果事務提交時PostgreSQL將廣播你的通知,使通知和相應的數據更改都可見於其他連接。

在客戶端中,您需要運行一個專門用於保持此地圖最新的線程。它將連接到PostgreSQL,LISTENwidgets_changed開始排隊通知,SELECT * FROM widgets填充地圖,並等待通知到達。 (檢查通知明顯是involves polling the JDBC driver,這很糟糕,但並不像你想象的那樣糟糕,請參閱PgNotificationPoller以獲得具體的實現。)一旦看到通知,查找指示的記錄並更新地圖。請注意,在初始SELECT *之前對LISTEN很重要,因爲記錄可能在SELECT *LISTEN之間更改。

這種方法不需要PostgreSQL知道任何有關您的應用程序。它只需發送通知;剩下的就是你的應用程序。沒有shell腳本,沒有HTTP,也沒有回調,可以讓您重新配置/重新部署應用程序,而無需重新配置數據庫。它只是一個數據庫,可以進行備份,恢復,複製等,而不會出現任何額外的複雜情況。類似地,你的應用程序沒有額外的複雜性:它所需要的只是一個到PostgreSQL的連接,你已經擁有了它。

+0

哇 - 真棒回答@willglynn(+1) - 只是好奇:我假設我可以通過JDBC運行'LISTEN'? 'PgNotificationPoller'就是Postgres在底層運行的東西,還是我需要添加到我的項目中才能使此NOTIFY/LISTEN模型起作用?再次感謝! – IAmYourFaja

+0

'LISTEN'是一個命令,它使PostgreSQL異步地將通知推送到你的連接,並在常規協議操作旁邊傳送特殊的'NOTIFY'相關消息。但是,JDBC驅動程序處理這些通知的方式有些特殊性(由於SSL限制),所以[顯然您需要發出垃圾查詢](http://postgresql.1045698.n5.nabble.com/-td2172662。 html)('「」')讓驅動程序看到通知可用。這比'libpq'更糟糕,它[不需要往返](http://bit.ly/Yt8txO),但仍然會跳動輪詢表。 – willglynn

+0

爲了更直接地回答你的問題,我發現''PgNotificationPoller'及其朋友['PgNotificationHelper'](http://wiki.postgresql.org/wiki/PgNotificationHelper)是我發現的兩件事,它們演示了JDBC'getNotifications()'功能。您可以使用這些或按照[驅動程序文檔](http://jdbc.postgresql.org/documentation/91/listennotify.html)中所述自行完成。 – willglynn