使用两个需要同步的数据库时如何实现乐观(或悲观)锁定?
How to implement an optimistic (or pessimistic) locking when using two databases that need to be in sync?
我正在研究一个解决方案,其中我们有两个用于以下目的的数据库:
- 用于搜索目的的 Elasticsearch
- 充当数据真实来源的 Postgres 数据库
我们的应用程序允许用户检索和更新产品,一个产品有多个属性:名称、价格、描述等...两个典型的用例是:
- 按名称检索产品:使用elasticsearch进行搜索,然后将ES检索到的ID用于Postgres的二次查询,以获取真实可信的数据(因此我们在大表上快速搜索,同时获取值得信赖的数据)
- 更新产品字段:我们允许用户更新任何产品信息(一种协作 wiki)。首先我们将数据存储在 Postgres 中,然后再存储到 Elasticsearch 中。
然而,正如我担心的那样,随着使用该应用程序的人数增加,我们 运行 进入了竞争条件;如果用户 #1 将产品名称更改为 "Banana",然后用户 #2 同时将产品名称更改为 "Apple",有时在 elasticsearch 中,最后保存的记录将是 "Banana" 而在 Postgres 中 "Apple" 将是最后一个值,在数据库之间造成严重的不一致。
所以我冒险阅读了 optimistic/pessimistic 锁定以解决我的问题,但到目前为止,我找到的所有文章都与你只使用 1 个关系数据库有关,并且提供的解决方案依赖于 ORM 实现(例如休眠)。但我们的 ES + Postgres 组合存储解决方案需要更多 "ballet"。
我可以使用哪些 techniques/options 来解决我的问题?
好吧,我可能会招致一些批评,但让我以我理解的方式向您解释一下。我的理解是 problem/concern 更像是一种架构视角,而不是 design/code 视角。
立即一致性,当然还有最终一致性
来自应用层
对于两个数据库之间的 immediate consitency
,实现它们的唯一方法是执行 polygot persistence in a transactional way
以便 Postgres
和 Elasticearch
中的相同数据得到更新或 none 会。我不会纯粹推荐这个,因为它会给应用程序带来很大的压力,你会发现很难scale/maintain。
所以基本上GUI --> Application Layer --> Postgres/Elasticsearch
Queue/Real 时间流机制
您需要有一个消息队列,以便在基于事件的方法中将更新发送到队列。
GUI --> Application Layer --> Postgres--> Queue --> Elasticsearch
最终一致性但不是立即一致性
有一个单独的应用程序,通常我们称之为indexer
。此工具的目的是从 postgres
执行更新并将它们推送到 Elasticsearch
。
您可以在 indexer
中拥有多个 single configuration per source
,而
- 执行
select *
和索引 everything
到 Elasticsearch
或 完全抓取 的选项
- 当你想 delete/reindex 整个数据进入
Elasticsearch
时,这将被使用
- 能够在 Postgres 中检测
only the updated rows
,从而将它们推送到 Elasticsearch 或 增量爬网
- 为此,您需要使用基于 postgres 行状态的 where 子句进行 select 查询,例如为最近更新的文档拉取状态为
0
的记录,或基于 timestamp
拉取最近 30 secs/1 min
更新的记录或根据您的需要。 增量查询
- 执行增量爬取后,如果使用
status
实现增量爬取,则需要将其状态更改为1
(成功)或'-1'(失败),以便在下一次抓取中,不会拾取相同的文档。 Post-增量查询
- 基本上将作业安排到 运行 以上查询作为索引操作的一部分。
基本上我们会有 GUI --> Application Layer --> Postgres --> Indexer --> Elasticsearch
总结
我不认为考虑故障证明方法是明智的,而是我们应该有一个可以在尽可能快的时间内恢复的系统,以提供两个不同数据源之间的一致性。
将系统解耦将极大地帮助扩展和找出与数据相关的问题 correctness/quality,同时将帮助您处理频繁的更新以及数据和更新的增长率它。
另外我再推荐一个link可以帮助
希望对您有所帮助!
我正在研究一个解决方案,其中我们有两个用于以下目的的数据库:
- 用于搜索目的的 Elasticsearch
- 充当数据真实来源的 Postgres 数据库
我们的应用程序允许用户检索和更新产品,一个产品有多个属性:名称、价格、描述等...两个典型的用例是:
- 按名称检索产品:使用elasticsearch进行搜索,然后将ES检索到的ID用于Postgres的二次查询,以获取真实可信的数据(因此我们在大表上快速搜索,同时获取值得信赖的数据)
- 更新产品字段:我们允许用户更新任何产品信息(一种协作 wiki)。首先我们将数据存储在 Postgres 中,然后再存储到 Elasticsearch 中。
然而,正如我担心的那样,随着使用该应用程序的人数增加,我们 运行 进入了竞争条件;如果用户 #1 将产品名称更改为 "Banana",然后用户 #2 同时将产品名称更改为 "Apple",有时在 elasticsearch 中,最后保存的记录将是 "Banana" 而在 Postgres 中 "Apple" 将是最后一个值,在数据库之间造成严重的不一致。
所以我冒险阅读了 optimistic/pessimistic 锁定以解决我的问题,但到目前为止,我找到的所有文章都与你只使用 1 个关系数据库有关,并且提供的解决方案依赖于 ORM 实现(例如休眠)。但我们的 ES + Postgres 组合存储解决方案需要更多 "ballet"。
我可以使用哪些 techniques/options 来解决我的问题?
好吧,我可能会招致一些批评,但让我以我理解的方式向您解释一下。我的理解是 problem/concern 更像是一种架构视角,而不是 design/code 视角。
立即一致性,当然还有最终一致性
来自应用层
对于两个数据库之间的 immediate consitency
,实现它们的唯一方法是执行 polygot persistence in a transactional way
以便 Postgres
和 Elasticearch
中的相同数据得到更新或 none 会。我不会纯粹推荐这个,因为它会给应用程序带来很大的压力,你会发现很难scale/maintain。
所以基本上GUI --> Application Layer --> Postgres/Elasticsearch
Queue/Real 时间流机制
您需要有一个消息队列,以便在基于事件的方法中将更新发送到队列。
GUI --> Application Layer --> Postgres--> Queue --> Elasticsearch
最终一致性但不是立即一致性
有一个单独的应用程序,通常我们称之为indexer
。此工具的目的是从 postgres
执行更新并将它们推送到 Elasticsearch
。
您可以在 indexer
中拥有多个 single configuration per source
,而
- 执行
select *
和索引everything
到Elasticsearch
或 完全抓取 的选项- 当你想 delete/reindex 整个数据进入
Elasticsearch
时,这将被使用
- 当你想 delete/reindex 整个数据进入
- 能够在 Postgres 中检测
only the updated rows
,从而将它们推送到 Elasticsearch 或 增量爬网- 为此,您需要使用基于 postgres 行状态的 where 子句进行 select 查询,例如为最近更新的文档拉取状态为
0
的记录,或基于timestamp
拉取最近30 secs/1 min
更新的记录或根据您的需要。 增量查询 - 执行增量爬取后,如果使用
status
实现增量爬取,则需要将其状态更改为1
(成功)或'-1'(失败),以便在下一次抓取中,不会拾取相同的文档。 Post-增量查询 - 基本上将作业安排到 运行 以上查询作为索引操作的一部分。
- 为此,您需要使用基于 postgres 行状态的 where 子句进行 select 查询,例如为最近更新的文档拉取状态为
基本上我们会有 GUI --> Application Layer --> Postgres --> Indexer --> Elasticsearch
总结
我不认为考虑故障证明方法是明智的,而是我们应该有一个可以在尽可能快的时间内恢复的系统,以提供两个不同数据源之间的一致性。
将系统解耦将极大地帮助扩展和找出与数据相关的问题 correctness/quality,同时将帮助您处理频繁的更新以及数据和更新的增长率它。
另外我再推荐一个link可以帮助
希望对您有所帮助!