内容简介:前段时间与同事一起为产品接入了 Elasticsearch 框架技术。从参与方案会议到搭建开发上线过程中有很多讨论点,故产生本文,希望藉此总结和分享一些经验。接触已有的业务时,它们的用途和联系,就跟它们的词义一样。
前言
前段时间与同事一起为产品接入了 Elasticsearch 框架技术。从参与方案会议到搭建开发上线过程中有很多讨论点,故产生本文,希望藉此总结和分享一些经验。
1. 业务模型
接触已有的业务时, 数据模型 是最早需要知道的信息。我和同事负责接入 Elasticsearch 的产品是一个业务繁多的通讯录,简化下来就是 3 个关键的模型,如下:
- 部门(Department)
- 人员(User)
- 标签(Tag)
它们的用途和联系,就跟它们的词义一样。
由此产生的业务如下:
- 通过 标签 查询 部门 、 人员
- 通过 部门 查询 人员
基于以上模型和业务,在典型的关系型数据库下,为了实现关联关系,自然会有额外的 关联表 :
- 部门人员关联表:每条记录包含1个部门,1个人员
- 标签对象关联表:每条记录包含1个标签,1个部门或人员
2. 需求
Elasticsearch 的特点有 全文检索、分布式、海量数据下近实时查询 。
当时为通讯录业务引入 Elasticsearch 的需求和目标如下:
- 多字段的匹配或模糊查询 。这些部门、人员、标签数据原本存储在 MySQL 中,如果要做匹配多个字段的模糊查询就比较吃力了,考虑一个常用功能 “输入姓名/手机号/拼音/首字母来查询人员”。而快速查询此类业务是 Elasticsearch 可以提供的。
- 基础模块能力 。其他业务模块也提出了类似全文检索的需求,因此在通讯录业务首次应用 es 时,要定义和提供好 es 的访问和 工具 方法,供其他模块在未来接入时,能复用一些实现,能保持一致的接口和命名风格等。
3. 索引设计
从原 MySQL 数据库表,到 Elasticsearch 的索引,数据模型的变化称为 异构 。
Elasticsearch 适合解决在 MySQL 中多条件或连表这样比较慢的查询业务,因此除了 原有 的信息字段,我们会再附加 3 个模型的 关联关系 到 es 索引中。
索引 字段 | 原有 | 关联关系 |
---|---|---|
部门 | 部门名<br/>完整部门路径名 | (无) |
人员 | 姓名<br/>拼音<br/>首字母<br/>手机号 | 父部门Id<br/>所有父级部门Id<br/>标签Id |
标签 | 标签名 | 部门Id<br/>人员Id |
(上表略去了一些无关本篇内容的字段,如 SaaS 平台的租户Id、每个对象的信息详情字段)
- 是否需要添加关联关系的字段,是由 业务需求 决定的。拿人员索引的 “所有父级部门Id” 举例子,因为有查询部门下所有人员(包括直属、子部门下的)的业务需求,所以会设计这么一个字段。
- 可以使用 Elasticsearch 的 分词功能 来记录关联关系的字段中。为该字段定义一个分隔模式为竖线 “|” 的分词器,把若干个关联Id存成一个拼接的字符串。
4. 版本选择
同事是个版本控,在选择版本时了解和考虑了非常多的信息。不过版本选择确实是为平台接入新技术时的一个重要考虑点。我们提出这个方案的当时( 2018年4月 ),对比了主要使用的云服务提供商的几个版本,考虑项可以按优先级概括为:
- 稳定的
- 案例资料多的
- 时新程度,包括 Elasticsearch版本 和 Lucene版本
- 我们已经使用了某家云服务提供商,会偏向再用其提供的服务
几个版本对比
我们当时选择了 Elasticsearch 6.2.2 版本。
v5.6.4
- 是 Spring 整合的各个框架中,支持数最多的版本
- 市面使用人数 较多,资料较多
- 其依赖的 Lucene 大版本是v6,较旧
v6.2.2
- 是当时 稳定 的版本中最新的,性能比 v5 好
v6.2.4
- 是当时最新的版本,修复了许多 bug
- 性能更好,是 官方推荐 的版本
- 官方的技术文档部分还没更新,得看旧文档
- 市面上找不到相应的人的使用资料
版本发展(于2019年4月)
在写本篇文章时,我再去了解了和 Elasticsearch版本 相关的变更:
Elasticsearch Lucene spring data elasticsearch
5. 导入已有数据
考虑到要使用 Elasticsearch 时,通常意味着已经有很多数据了。首次使用自然会有导入已有数据的过程,而且这些数据量都是很大的。
我们的方案是 JDBC 查询并提交给 es。设计要点有:
- 分批 。数据量之大已经无法一次存到内存中。数据按明确的边界划分而独立,会让多线程处理、日志记录、重试都变得轻松。按租户来划分就是一种好的方式。
- 缓慢 。避免影响线上的服务,同时适当给 JVM 回收和 Elasticsearch 处理留一点时间。
- 异常 。信息汇总和失败重试。
具体设计细节如下:
- 为 SaaS 系统的 每个租户 创建一个任务,提交到
ExecutorCompletionService
。 - 在该租户的 任务 中:
一次查询所有部门;
分页查询所有人员、部门人员关联;
一次查询所有标签,标签对象关联; - 将 关联关系 做成便于查询的数据结构,以用于添加 es 文档时的快速查询。
例如,映射<人员,部门>可用于查询:人员所属的部门;
例如,映射<部门,标签>可用于查询:部门所贴的标签;
用到了 Guava 的Multimap
,以达到类似于 Map<String, Set<String>> 的效果。 - 建立新增 es 文档的 批量请求
BulkRequest
。对于每个对象,都可以用上一步做好的结构快速获取其关联关系。 - 提交 批量新增 请求给 es。
6. 数据源同步
我们的 MySQL 数据同步到 Elasticsearch 的方案,是在应用层基于 事件通知 进行的。以 人员 对象为例,步骤如下:
- 人员的增删查改事件,都会通知给其他订阅者。这是已有的逻辑;
- 设计一个“记录人员变动”订阅者,被通知时,将变动储存起来;
- 设计一个“Es同步”定时任务,每天凌晨,取出变动记录,提交到 Es,之后删除变动记录;
看到这个方案,你可能会问为什么不使用像 Logstash 等成熟的框架或插件,而是自写一套同步方法?原因如下:
- 我们选择的 MySQL 云服务提供商在当时 没有 提供 binlog 日志访问。这使我们无法选择一些基于日志的同步方案。
- 部门、人员、标签的数据表原本没有像 update_time 这样的——能反映变更的列。故又可以排除基于时间去增量同步的方案。
- 人员、标签表的数据量很大,如果要增加一列 update_time 并加上索引,带来的成本有:额外的 储存空间 (我们购买的云服务空间每增长百G每年的成本大约是1000元);新字段给应用层带来的 维护成本 。
- 设计出来的 Es 索引和 MySQL 表的 字段不同 。一些在 Es 索引中新增的字段,是需要在 MySQL 中做额外查询才能得到的。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Redis 主从同步配置实践
- 携程 Redis 海外机房数据同步实践
- 有赞订单同步的探索与实践
- 携程 Redis 跨 IDC 多向同步实践
- 爱作业口算同步练,TensorFlow Lite 实践
- 有赞亿级订单同步的探索与实践
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
函数式算法设计珠玑
Richard Bird / 苏统华、孙芳媛、郝文超、徐琴 / 机械工业出版社 / 2017-4-1 / 69.00
本书采用完全崭新的方式介绍算法设计。全书由30个珠玑构成,每个珠玑单独列为一章,用于解决一个特定编程问题。这些问题的出处五花八门,有的来自游戏或拼图,有的是有趣的组合任务,还有的是散落于数据压缩及字串匹配等领域的更为熟悉的算法。每个珠玑以使用函数式编程语言Haskell对问题进行描述作为开始,每个解答均是诉诸于函数式编程法则从问题表述中计算得到。本书适用于那些喜欢学习算法设计思想的函数式编程人员、......一起来看看 《函数式算法设计珠玑》 这本书的介绍吧!
html转js在线工具
html转js在线工具
RGB CMYK 转换工具
RGB CMYK 互转工具