使用两个需要同步的数据库时,如何实现乐观(或悲观)锁定?

时间:2018-10-29 12:35:40

标签: postgresql elasticsearch concurrency optimistic-locking pessimistic-locking

我正在研究一种解决方案,其中有两个用于以下目的的数据库:

  • 用于搜索目的的Elasticsearch
  • 一个Postgres数据库,可作为数据的真实来源

我们的应用程序允许用户检索和更新产品,并且产品具有多个属性:名称,价格,说明等。两个典型的用例是:

  • 按名称检索产品:使用Elasticsearch执行搜索,然后将ES检索到的ID用于针对Postgres的辅助查询,以获取实际的和可信赖的数据(因此,我们在获取可信赖的数据的同时对大表进行了快速搜索)
  • 更新产品字段:我们允许用户更新任何产品信息(一种协作式Wiki)。首先,我们将数据存储在Postgres中,然后存储到Elasticsearch中。

但是,正如我所担心的,以及随着使用该应用程序的人数的增加,我们陷入了竞赛状态;如果用户#1将产品名称更改为“香蕉”,然后用户#2同时将产品名称更改为“苹果”,则有时在elasticsearch中保存的最后一条记录为Postgres中的“香蕉” “ Apple”将是最后一个值,从而在数据库之间造成严重的不一致。

因此,为了解决我的问题,我冒昧阅读了乐观/悲观锁定,但是到目前为止,当您仅使用1个关系数据库时,我发现的所有文章都是相关的,并且提供的解决方案依赖于ORM实现(例如Hibernate) 。但是我们的ES + Postgres组合存储解决方案需要更多的“芭蕾舞”。

我可以使用哪些技术/选项来解决自己的问题?

1 个答案:

答案 0 :(得分:1)

好吧,我可能会吸引一些批评家,但请允许我以我理解的方式向您解释。我了解的是,这个问题/关注点更多是从架构角度而不是设计/代码角度。

立即一致性,当然还有最终的一致性

从应用程序层

对于两个数据库之间的immediate consitency,实现它​​们的唯一方法是执行polygot persistence in a transactional way,以便更新PostgresElasticearch中的相同数据或者他们都不愿意。我不会纯粹推荐这样做,因为它会给应用程序带来很大压力,并且您会发现扩展/维护非常困难。

所以基本上是GUI --> Application Layer --> Postgres/Elasticsearch

队列/实时流机制

您需要有一个消息队列,以便在基于事件的情况下将更新发送到队列。

GUI --> Application Layer --> Postgres--> Queue --> Elasticsearch

最终一致性,但不是立即一致性

有一个单独的应用程序,通常将其称为indexer。该工具的目的是从postgres执行更新并将其推送到Elasticsearch

您可以在indexer中拥有多个single configuration per source

  • 执行select *并将everything索引到Elasticsearch 完全爬网 的选项
    • 当您要将整个数据删除/重新索引到Elasticsearch中时,将使用该方法
  • 能够在Postgres中检测only the updated rows,并将其推送到Elasticsearch或 增量爬网
    • 为此,您将需要有一个基于where子句的select查询,该查询基于postgres行上的状态,例如为最近更新的文档提取状态为0的记录,或者根据timestamp提取最近30 secs/1 min或根据您的需要更新的记录。 增量查询
    • 执行增量爬网后,如果使用status实现增量爬网,则需要将其状态更改为1(成功)或'-1'(失败),以便在下次抓取相同文档不会被拾取。 后增量查询
    • 基本上将作业安排为在查询之上运行,这是索引操作的一部分。

基本上我们会有GUI --> Application Layer --> Postgres --> Indexer --> Elasticsearch

摘要

我认为考虑故障预防方法不是明智的选择,而是我们应该拥有一个可以在两个不同数据源之间提供一致性的情况下尽快恢复的系统。

将系统解耦将极大地帮助扩展和解决与数据正确性/质量有关的问题,同时将帮助您处理频繁的更新以及数据和更新的增长率。

我还建议另外一个link可以帮助

希望有帮助!