索引更新如何用于 Solr 和 Elasticsearch?
How the index updates works for Solr and Elasticsearch?
我有一个使用事件溯源和命令查询责任分离模式的应用程序。命令部分开发完成,我必须决定如何实现查询部分。
我的系统处理客户订单,因此当订单事件到达时,该订单会使用 orderId 和订单负载进行处理。问题是,在这种形式下,只有 whay 查询订单超过 orderId,所以我不能问一个问题,比如给我系统中状态为 OPEN 的所有订单。
对于这部分我必须使用查询部分,我对查询部分的潜在技术实现,像 PostGre DB 这样的经典解决方案或者我认为更优雅的方式 Solr/Elasticsearch。
我对 Solr/Elasticsearch 有一个基本的 knowledge/experience,我想利用这个机会学习更多,但我的困境来了。我们公司的其他一些部门已经在使用 Elasticsearch,那个部门的一位同事告诉我,elasticsearch 中的更新不是一个好主意,我不太理解他的论点,所以我想在这里问一下我打算做什么所以你可以告诉我,这是个坏主意,或者 Solr 更适合它。
我计划将订单的每个状态更改作为 Elasticsearch 的更新发送,因此它看起来如下所示。
id
Status
Customer
Items
orderId1
->
order.SUBMITTED
order.Customer
order.Items
orderId1
->
order.CHANGED
order.Customer1
order.Items
orderId1
->
order.PROCESSING
order.Customer1
order.Items
orderId1
->
order.ON_DELIVERY
order.Customer1
order.Items
orderId1
->
order.COMPLETE
order.Customer1
order.Items
如您所见,我必须将 orderId 的几个更新发送到 Elasticsearch/Solr。
所以我的同事告诉我,Elasticsearch 中的索引文档是不可变的,当我发送 order.SUBMITTED 要索引的事件时,它会创建文档,但 order.CHANGED 事件不会更新文档而是创建另一个。现在我不能完全判断这个结果,对于我的业务案例(我将询问我的 Customer1 的订单,我将看到状态 SUBMITTED 和 CHANGED,2 条记录作为查询响应)或操作(额外的负载和存储)。
我是否正确理解了 Eleasticsearch 的行为?如果是,Solr 的行为会有什么不同吗?
如果理解正确,两者的行为相同,我可以设计任何不同的东西来帮助实现我的目标吗?
最后我对这个解决方案使用 PostGre 没有问题,我只是认为 Elasticsearch 或 Solr 是解决这个问题的更自然的选择。你怎么看?
感谢解答。
你同事说的对,Elasticsearch(ES)的更新成本高,更新不可变,但这并不意味着ES不适合更新频繁的系统,实际上是因为它的可扩展性和分布式特性它的首选并被用于 high-throughput 和低延迟系统(包括搜索系统)。
你有一些误解,我会尽力解释它们。
- ES和Solr都是基于Lucene的,更新代价高或者不可变的更新是Lucene的属性,所以不管你选择ES还是Solr,你都会底层使用Lucene并且会具有相同的更新机制。
- 更新是不可变的,这并不意味着您的旧订单状态将始终在索引中,例如,最初您的订单状态是
SUBMITTED
,后来您将其更新为 CHANGED
, 所以即使它是不可变的但是当你查询订单状态时,你会得到最新的状态(如果 refresh 发生在索引上,在 ES 中默认是 1 秒), 除了永久删除旧的文档(在合并过程中发生,在#3 中解释),ES 将旧文档标记为已删除(通过更新布尔标志删除软删除,在文档更新时),因此在您搜索期间不会返回这些软删除的文档。
- ES 会定期删除旧文档,因此在您的情况下
order
状态 SUBMITTED
将在 merge process 期间从索引中删除,这样旧文档就会被删除,并且您的索引大小不增长。
同样重要的是要理解,这种不可变更新为提高 search/read 性能提供了巨大的好处,因为现在这些段(包含 ES 中的文档)可以用于multi-threading env 以及由于不变性原因可以缓存。
我有一个使用事件溯源和命令查询责任分离模式的应用程序。命令部分开发完成,我必须决定如何实现查询部分。
我的系统处理客户订单,因此当订单事件到达时,该订单会使用 orderId 和订单负载进行处理。问题是,在这种形式下,只有 whay 查询订单超过 orderId,所以我不能问一个问题,比如给我系统中状态为 OPEN 的所有订单。
对于这部分我必须使用查询部分,我对查询部分的潜在技术实现,像 PostGre DB 这样的经典解决方案或者我认为更优雅的方式 Solr/Elasticsearch。
我对 Solr/Elasticsearch 有一个基本的 knowledge/experience,我想利用这个机会学习更多,但我的困境来了。我们公司的其他一些部门已经在使用 Elasticsearch,那个部门的一位同事告诉我,elasticsearch 中的更新不是一个好主意,我不太理解他的论点,所以我想在这里问一下我打算做什么所以你可以告诉我,这是个坏主意,或者 Solr 更适合它。
我计划将订单的每个状态更改作为 Elasticsearch 的更新发送,因此它看起来如下所示。
id | Status | Customer | Items | |
---|---|---|---|---|
orderId1 | -> | order.SUBMITTED | order.Customer | order.Items |
orderId1 | -> | order.CHANGED | order.Customer1 | order.Items |
orderId1 | -> | order.PROCESSING | order.Customer1 | order.Items |
orderId1 | -> | order.ON_DELIVERY | order.Customer1 | order.Items |
orderId1 | -> | order.COMPLETE | order.Customer1 | order.Items |
如您所见,我必须将 orderId 的几个更新发送到 Elasticsearch/Solr。
所以我的同事告诉我,Elasticsearch 中的索引文档是不可变的,当我发送 order.SUBMITTED 要索引的事件时,它会创建文档,但 order.CHANGED 事件不会更新文档而是创建另一个。现在我不能完全判断这个结果,对于我的业务案例(我将询问我的 Customer1 的订单,我将看到状态 SUBMITTED 和 CHANGED,2 条记录作为查询响应)或操作(额外的负载和存储)。
我是否正确理解了 Eleasticsearch 的行为?如果是,Solr 的行为会有什么不同吗?
如果理解正确,两者的行为相同,我可以设计任何不同的东西来帮助实现我的目标吗?
最后我对这个解决方案使用 PostGre 没有问题,我只是认为 Elasticsearch 或 Solr 是解决这个问题的更自然的选择。你怎么看?
感谢解答。
你同事说的对,Elasticsearch(ES)的更新成本高,更新不可变,但这并不意味着ES不适合更新频繁的系统,实际上是因为它的可扩展性和分布式特性它的首选并被用于 high-throughput 和低延迟系统(包括搜索系统)。 你有一些误解,我会尽力解释它们。
- ES和Solr都是基于Lucene的,更新代价高或者不可变的更新是Lucene的属性,所以不管你选择ES还是Solr,你都会底层使用Lucene并且会具有相同的更新机制。
- 更新是不可变的,这并不意味着您的旧订单状态将始终在索引中,例如,最初您的订单状态是
SUBMITTED
,后来您将其更新为CHANGED
, 所以即使它是不可变的但是当你查询订单状态时,你会得到最新的状态(如果 refresh 发生在索引上,在 ES 中默认是 1 秒), 除了永久删除旧的文档(在合并过程中发生,在#3 中解释),ES 将旧文档标记为已删除(通过更新布尔标志删除软删除,在文档更新时),因此在您搜索期间不会返回这些软删除的文档。 - ES 会定期删除旧文档,因此在您的情况下
order
状态SUBMITTED
将在 merge process 期间从索引中删除,这样旧文档就会被删除,并且您的索引大小不增长。
同样重要的是要理解,这种不可变更新为提高 search/read 性能提供了巨大的好处,因为现在这些段(包含 ES 中的文档)可以用于multi-threading env 以及由于不变性原因可以缓存。