Elasticsearch 查询和数据同步 - 记一次技术实践

2019-04-19  本文已影响0人  mokou591

前言

前段时间与同事一起为产品接入了 Elasticsearch 框架技术。从参与方案会议到搭建开发上线过程中有很多讨论点,故产生本文,希望藉此总结和分享一些经验。

1. 业务模型

接触已有的业务时,数据模型是最早需要知道的信息。我和同事负责接入 Elasticsearch 的产品是一个业务繁多的通讯录,简化下来就是 3 个关键的模型,如下:

它们的用途和联系,就跟它们的词义一样。
由此产生的业务如下:

3个模型的简化联系.png

基于以上模型和业务,在典型的关系型数据库下,为了实现关联关系,自然会有额外的关联表

2. 需求

Elasticsearch 的特点有全文检索、分布式、海量数据下近实时查询
当时为通讯录业务引入 Elasticsearch 的需求和目标如下:

3. 索引设计

从原 MySQL 数据库表,到 Elasticsearch 的索引,数据模型的变化称为异构
Elasticsearch 适合解决在 MySQL 中多条件或连表这样比较慢的查询业务,因此除了原有的信息字段,我们会再附加 3 个模型的关联关系到 es 索引中。

索引 \ 字段 原有 关联关系
部门 部门名
完整部门路径名
(无)
人员 姓名
拼音
首字母
手机号
父部门Id
所有父级部门Id
标签Id
标签 标签名 部门Id
人员Id

(上表略去了一些无关本篇内容的字段,如 SaaS 平台的租户Id、每个对象的信息详情字段)

4. 版本选择

同事是个版本控,在选择版本时了解和考虑了非常多的信息。不过版本选择确实是为平台接入新技术时的一个重要考虑点。我们提出这个方案的当时(2018年4月),对比了主要使用的云服务提供商的几个版本,考虑项可以按优先级概括为:

  1. 稳定的
  2. 案例资料多的
  3. 时新程度,包括 Elasticsearch版本 和 Lucene版本
  4. 我们已经使用了某家云服务提供商,会偏向再用其提供的服务

几个版本对比

我们当时选择了 Elasticsearch 6.2.2 版本。

v5.6.4

v6.2.2

v6.2.4

版本发展(于2019年4月

在写本篇文章时,我再去了解了和 Elasticsearch版本 相关的变更:

5. 导入已有数据

考虑到要使用 Elasticsearch 时,通常意味着已经有很多数据了。首次使用自然会有导入已有数据的过程,而且这些数据量都是很大的。
我们的方案是 JDBC 查询并提交给 es。设计要点有:

具体设计细节如下:

  1. 为 SaaS 系统的每个租户创建一个任务,提交到ExecutorCompletionService
  2. 在该租户的任务中:
    一次查询所有部门;
    分页查询所有人员、部门人员关联;
    一次查询所有标签,标签对象关联;
  3. 关联关系做成便于查询的数据结构,以用于添加 es 文档时的快速查询。
    例如,映射<人员,部门>可用于查询:人员所属的部门;
    例如,映射<部门,标签>可用于查询:部门所贴的标签;
    用到了 Guava 的 Multimap,以达到类似于 Map<String, Set<String>> 的效果。
  4. 建立新增 es 文档的批量请求BulkRequest。对于每个对象,都可以用上一步做好的结构快速获取其关联关系。
  5. 提交批量新增请求给 es。

6. 数据源同步

我们的 MySQL 数据同步到 Elasticsearch 的方案,是在应用层基于事件通知进行的。以人员对象为例,步骤如下:

  1. 人员的增删查改事件,都会通知给其他订阅者。这是已有的逻辑;
  2. 设计一个“记录人员变动”订阅者,被通知时,将变动储存起来;
  3. 设计一个“Es同步”定时任务,每天凌晨,取出变动记录,提交到 Es,之后删除变动记录;

看到这个方案,你可能会问为什么不使用像 Logstash 等成熟的框架或插件,而是自写一套同步方法?原因如下:

上一篇 下一篇

猜你喜欢

热点阅读