本文始发于知乎Elasticsearch专栏:从MySQL建立Elasticsearch索引-索引
接上文从MySQL建立Elasticsearch索引-引言,本文介绍一下我们实现索引创建时的一些思路。
目标
框架以Jar包的形式提供,通过配置(XML)提供规则,支持插件开发,支持全量、增量等。
因为希望尽量减少开发量,所以不要求使用方提供平表,因此需要考虑如何将平表
概念
- 全量:即使用全部数据创建一个新的索引
- 增量:按照时间范围或者给定的规则,把变化的数据同步到ES
- 插件:本框架内定义了一个插件接口,用于特定需求自行开发,并接入到现有的配置文件中
- 分批参数:SQL中由框架填充的参数,类似${id}等
配置
以用户(users)为例,配置有三种文件:
- users.mapping,保存了索引的配置,每次全量的时候会读取本文件进行索引创建
- rule,规则文件,里面主要定义了对应SQL和插件的配置
- users-all.rule,全量规则,规则中以主表为主体,支持以Top、Limit的形式对数据进行分批获取,分批参数在SQL里可以定义为${id},框架会自动填充该值,以保证能够拉取到全量的数据
- users-inc.rule,按照时间范围进行增量,分批参数支持在SQL中使用${startTime}和${endTime}
- users-spec.rule,按照指定的主表的主键,获取数据及更新索引的操作
- users-partial.rule,框架接入了阿里的Canal,本规则定义了各种表变化时,如果取到主表Id,以使用spec进行数据更新
- users.plugin,以上的rule主要提供了主表数据的获取方法,plugin文件则提供了各种关联表的信息获取方式,可以使用SQL,或者自定义的插件
全量索引实现关键点
为了保证索引的性能、监控、正确性等,实现时进行了以下设计。
(一)索引的维护
ES使用分布式、Replica、Snapshot机制保证索引的有效及集群稳定性。我们综合考虑后决定放弃Snapshot机制,通过定时/不定时创建全新全量索引,索引名字以${indexName}-{yyyy-MM-dd}的格式定义。正进行全量的索引关联上${indexName}_F的别名,正在使用的索引关联上${indexName}的别名,这样代码里可以不用关心应该读取或者使用哪个索引,合适的场景使用合适的别名即可。
(二)索引的性能
此处专指创建索引的性能,ES的性能是老话题了。
首先,为了保证全量的性能,创建索引时会调整mapping参数,类似refresh_interval改成-1,number_of_replicas改成0,添加默认slowlog设置。
索引过程中,控制bulk请求体的总大小,保证合适的分批大小的数据一并提交到ES。如果失败简单重试三次,如果三次都失败则认为失败,退出并删除当前索引,以保证线上ES数据干净准确。
(三)索引的变更
索引完成后,检查当前索引文档数和正使用索引文档数差异,如果大于配置的阈值,则认为此次索引创建有问题,删除索引并退出;做强制合并,减少segments数,提高搜索性能;恢复refresh_interval、number_of_replicas等设置;等待新索引状态变成GREEN后,将${indexName}切换到新的索引上,以使新索引生效。
最后,检查以${indexName}-{yyyy-MM-dd}格式命名的索引有几份,将多于指定个数的较老的索引删除,将多于指定个数的索引状态改为Close。这样可以尽可能提供磁盘内存利用率,减少不必要的损耗,又能在一定程度上保证数据可用。
以上,即完成了全量索引的创建。
增量索引实现关键点
增量索引因为场景比较多,所以规则也分了几种:
- inc,使用${startTime}和${endTime}在SQL中代替时间范围,框架会自动保存上次执行时间,以使整个增量整体不断滚动更新。实际使用时,因为有多个关联表导致SQL写起来比较复杂,以及部分增量数据过大,对DB有一定压力,因此不推荐使用此种方式。数据相对简单的场景可以使用。
- spec,在知道主表数据变化范围的时候使用,也是目前我们推荐的一种方式。使用主键查找数据,所有的表都是主键查询,影响范围也很明确。
- partial,针对canal做了单独封装的规则,用户获取canal的变化类型(更新、删除),变化的主表Id,用于使用spec的方式进行数据更新。
暂时没有使用部分更新的原因是,关联表与主表的映射关系比较复杂,有1:1,1:N,M:N;并且目前按照主键更新数据的方式,对DB等压力不大;加上spec的方式逻辑清晰,有利于维护和开发。
扩展性
SQL不是万能的,比方说我们部分数据需要从其他微服务取,或者SQL逻辑复杂建议代码实现,这时候就可以使用我们的插件机制了。默认框架提供了一个很强大的插件,支持Distinct、Merge、Mapping等功能,可以满足80%的关联数据的场景了。其他的场景以及需要微服务的场景,支持用户自己实现指定插件,通过配置文件,即可接入现有的框架体系中。以此能支持目前我们全部需求。
下一篇,我们将分享我们搜索模块的实现思路。
本文地址:http://elasticsearch.cn/article/13416