大家好,我是欧达克。
平时工作中,我们或多或少有接触到 ES,就算没接触过,也知道它是倒排索引,知道它对传统关系型数据库无法很好支持的全文检索是一大利器。那我们如何做 ES 的全量数据更新呢?
很多朋友可能会说,ES 为什么要做全量数据更新?本身 ES 承载的数据量就很大,做全量更新耗时很长。这个说法没问题,如果你使用的 ES 不需要有全量更新的场景,那这篇文章确实不适合你,但是如果你和我一样,在工作中有遇到需要将数据库的数据,全量更新到 ES ,那本篇文章会给你提供另一个思路。
首先介绍一下 ES 的一些基本术语:
术语 | 说明 |
---|---|
文档(document) | 文档是可以被索引的信息的基本单位。例如,您可以为单个客户提供一个文档,单个产品提供另一个文档,以及单个订单提供另一个文档。 |
索引(index) | 索引是具有相似特性的文档集合。例如,可以为客户数据提供索引,为产品目录建立另一个索引,以及为订单数据建立另一个索引。 |
索引别名(index alias) | 可以为一个或者多个索引提供一个别名,从而实现对索引的抽象和封装。它可以简化索引的访问,可以在不改变客户端代码的情况下,动态地切换或者更新索引。 |
本文最核心的,就是 ES 中索引别名的使用。
现假设一个场景,每天有些跑批数据,会定时更新到数据库,我们需要将数据库的数据全量更新到 ES,业务上有两个要求:
- 更新期间,需要保证服务可用;
- 更新失败,需要保证服务可用;
这要求不能将索引一把删除,然后再慢慢写数据,因为这样会导致更新期间服务不可用,万一某些数据异常,可能导致更新失败。我们还可以在更新的时候,将数据写到一个新的索引,更新结束后,再从新的索引中查,思路是对的,那方案呢?难道每次在查询的时候,都要判断从新索引查还是旧索引查吗?未免太过麻烦,这时候可以用到索引别名,不需要改查询逻辑。
为了实现目标,现在我们需要:
- 一个主索引:index_main;
- 一个更新索引:index_update;
- 一个索引别名:index_alias;
详细步骤
Step1:
创建主索引 index_main
和索引别名 index_alias
,索引别名指向主索引,这时候 ES 中的数据还都是空的。
Step2:
数据更新时,创建更新索引 index_update
,数据更新到 index_update
Step3:
数据更新结束后,将索引别名 index_alias
,指向更新索引 index_update
,再删除主索引 index_main
,这时候更新索引 index_update
已经完成数据更新。
Step4:
下次数据更新时,创建主索引 index_main
, 数据更新到主索引
Step5:
数据更新结束后,将索引别名 index_alias
,指向主索引 index_main
,再删除更新索引 index_update
之后就是循环 Step2-Step5
总结
以上就是索引别名在数据更新时的应用,只有在新索引完全构建好之后,才会将索引别名指向新的索引,相比于直接删除索引再重建,该方案能够保证在索引构建失败的时候,不影响原索引中的数据,也就是说当构建失败的时候,索引也能够用,只是数据可能不是最新的,但是不会导致整个功能不可用,这也是该方案的优势。
核心就一句话,即索引别名的定义:可以为一个或者多个索引提供一个别名,从而实现对索引的抽象和封装。它可以简化索引的访问,可以在不改变客户端代码的情况下,动态地切换或者更新索引。