通知postgres对java应用程序的更改 问题
我正在为几十万种产品建立一个postgres数据库。我将设置一个索引(Solr或ElasticSearch)以缩短复杂搜索查询的查询时间 现在的重点是如何让索引与数据库同步? 在过去,我有一种应用程序,它定期轮询数据库以检查应该进行的更新,但是我会有一个过时的索引状态时间(从数据库更新到索引更新) 我更喜欢这样一种解决方案:数据库将通知我的应用程序(java应用程序)数据库中的某些内容已更改,此时应用程序将决定是否需要更新索引。更准确地说,我将构建一种生产者和消费者结构,希望复制副本将收到来自postgres的通知,指出发生了变化,如果这与索引数据相关,那么它将存储在一个更新堆栈中。使用者将使用此堆栈并构建要存储到索引中的文档 可能的解决方案 一种解决方案是编写一种副本端点,其中应用程序将作为一个postgres实例,用于从原始数据库复制数据。有人对这种方法有经验吗 对于这个问题,我还有什么其他解决方案? 对于这个问题,我还有什么其他解决方案 用于告诉你的应用程序事情已经改变 您可以从一个触发器发送通知postgres对java应用程序的更改 问题,java,postgresql,indexing,synchronization,replication,Java,Postgresql,Indexing,Synchronization,Replication,我正在为几十万种产品建立一个postgres数据库。我将设置一个索引(Solr或ElasticSearch)以缩短复杂搜索查询的查询时间 现在的重点是如何让索引与数据库同步? 在过去,我有一种应用程序,它定期轮询数据库以检查应该进行的更新,但是我会有一个过时的索引状态时间(从数据库更新到索引更新) 我更喜欢这样一种解决方案:数据库将通知我的应用程序(java应用程序)数据库中的某些内容已更改,此时应用程序将决定是否需要更新索引。更准确地说,我将构建一种生产者和消费者结构,希望复制副本将收到来自p
通知
,该触发器还记录队列表中的更改
您需要一个PgJDBC连接,该连接已为您正在使用的事件发送了一个LISTEN
。如果您使用SSL,它必须通过定期发送空查询(“
)来轮询数据库;若您并没有使用SSL,那个么可以通过使用异步通知检查来避免这种情况。您需要从连接池中打开连接
对象,才能将基础连接强制转换为PgConnection
以使用侦听/通知。看
生产者/消费者部分将更加困难。要在PostgreSQL中拥有多个碰撞安全并发使用者,您需要将建议锁定与pg\try\u advical\u lock(…)
一起使用。如果您不需要并发消费者,那么很容易,您只需选择。。。每次更新一行的限制为1
希望9.4将包括一个更简单的方法,通过更新,跳过锁定的行,因为它正在开发中。要使用LISTEN and NOTIFY of postgres,您需要使用一个支持异步通知的驱动程序。postgres JDBC驱动程序不支持异步通知
要通过应用服务器的通道持续侦听,请使用pgjdbc ng 0.6驱动程序
它支持异步通知,无需轮询 通常,我建议使用实现松耦合。然后,如果您决定交换数据库,则索引端的代码不会更改
如果您想使用紧耦合,我建议您使用
.
在Java中,使用非常重要,因为它支持异步
无轮询的通知
下面是一个异步模式(基于):
在其他语句中,您现在可以执行notifytest,'这是一个有效负载'代码>。您还可以在触发器等中执行NOTIFY
。仅针对记录跳过锁定的在PG 9.5
中引入,避免使用管理功能,如PG\u try\u advisional\u lock
。是的,尽管建议锁定仍然有一些非常方便的用途。你不必再像上面那样在排队时使用它们,但它们在其他领域仍然非常方便。
import com.impossibl.postgres.api.jdbc.PGConnection;
import com.impossibl.postgres.api.jdbc.PGNotificationListener;
import com.impossibl.postgres.jdbc.PGDataSource;
import java.sql.Statement;
public static void listenToNotifyMessage() {
PGDataSource dataSource = new PGDataSource();
dataSource.setHost("localhost");
dataSource.setPort(5432);
dataSource.setDatabase("database_name");
dataSource.setUser("postgres");
dataSource.setPassword("password");
PGNotificationListener listener = (int processId, String channelName, String payload)
-> System.out.println("notification = " + payload);
try (PGConnection connection = (PGConnection) dataSource.getConnection()) {
Statement statement = connection.createStatement();
statement.execute("LISTEN test");
statement.close();
connection.addNotificationListener(listener);
// it only works if the connection is open. Therefore, we do an endless loop here.
while (true) {
Thread.sleep(500);
}
} catch (Exception e) {
System.err.println(e);
}
}