以前分享了一篇文章,介绍咱们的ES广告倒排索引的架构与优化,我就不介绍了,建议先去看下这篇文章,再回来看这篇,下面只放下以前的架构图网络
原有架构是在代码中写 MQ 消息,而后 indexbuilder 消费消息,写入到两个索引中。但这种方式有个不足是不能覆盖全部的订单或创意变动,因此倒排索引中的数据有的时候和 DB 中是不一致的。同时代码维护起来也比较麻烦。后面咱们就引入了阿里开源的框架 canal ,它能够监听 MySQL 的 binlog 的变动,而后把日志发到 Kafka 中,这样咱们只须要在 indexbuilder 这个工程中消费 Kafka 的消息就好了,省去了在 dsp_adinfo 中发消息。并且 binlog 的变动能够覆盖全部的变动操做。架构
以前 index_builder 部署在物理机上,且 builder 采用主备部署,经过争抢用 zookeeper 实现的分布式锁来决定谁是主,迁移到云平台后,就去掉了这种对主备部署的方式,由于云平台有自动修复的策略。app
注意框架
咱们部署的两个 builder 一个为 m 索引,一个为 f 索引,经过环境变量 dspindexname 区分是 m 索引 仍是 f 索引。同时由于这两个 builder 都要消费 Kafka 的消息,但咱们知道 Kafka 处于同一个消费组的消费者只有一个能消费消息,因此要把两个 builder 放到不一样的消费组中,即设置不一样的 group_id,一样也是经过环境变量区分elasticsearch
增长了检查 DB 和 ES倒排索引中的数据一致性的定时任务,每 10 分钟执行一次,若是发现不一致会发短信通知,正常状况下数据都是一致的分布式
经过上面的一点点演进,总体架构以下所示源码分析
由于咱们只部署了一套 ES 集群,两个索引都在上面,只是经过别名访问,完成索引的切换,这就存在单点问题,一旦集群出现问题,后果不堪设想。性能
就像墨菲定律所言学习
若是事情有变坏的可能,无论这种可能有多小,它总会发生优化
咱们的场景是读多写少,且索引占用内存比较小,因此设置的主分片是 1 ,副本分片是 节点数-1,这样就能够保证每一个节点都保存全部数据,能够减小在路由分片或节点的网络消耗。
但在一次上线过程当中,忘记修改副本数了,因此副本数默认是 1,而后切换到该索引后,短期(大约几十秒)内就致使 ES 集群瘫痪,节点内存爆满且不响应任何请求,由于主备索引都在一个 ES 集群中,因此想切回主索引也切不回去了,致使咱们一段时间检索不出来广告,从而影响出价。最后没有办法只能在入口处把流量暂停,而后重启 ES,很尴尬的是,咱们没有准备批量重启 ES 集群的脚本,只能挨个节点登陆重启,也浪费了一些时间。再 ES 集群重启完后,从新构建索引并正确设置副本数,再打开流量,才恢复了正常,当时真的心惊肉跳,至今记忆犹新。
咱们一个 ES 集群部署了 35 个节点,设置的主分片是 1,副本分片是节点数-1,即 34,这样作的好处是每一个节点都有完整的数据,当请求到该节点后,直接查询数据就能够返回了,省去了路由到其余节点带来的网络消耗
而忘记修改副本数,即默认的是 1,这样出现的状况是,整个 ES 集群 35 个节点,只有 2 个节点有数据,其余节点是没有数据的,可是每一个节点都是均匀的接收请求,可是这些没有数据的节点会把请求转发到有数据的两个节点,也就是这两个节点要承担其余没有数据的 33 个节点的请求压力,因此最后撑爆了整个集群
此次线上问题后,咱们作了反思,也须要采用一些对策来避免相似的状况发生
1. 主备索引部署在同一个 ES 集群上,存在单点问题,因此须要再部署一个 ES 集群,实现物理隔离
2. 提供重启整个 ES 集群的脚本,以备在出现问题时能够快速重启集群
3. 经过别名方式切换索引是 100% 流量切换,也容易出现问题,因此须要一个灰度慢慢切换的方式
4. 切换索引时要增长必要的检查项
5. 调用 ES 增长熔断机制,当 ES 集群出现故障时触发熔断,保护 ES 集群和服务
首先就是从新部署了一套 ES 集群,实现物理隔离,避免一个 ES 集群出问题,影响到另外一个集群
其次在做业平台中增长重启 ES 的脚本
而后就是经过引入 Nacos 配置中心,配置流量分配比例,从而实现灰度切换流量。同时支持配置变动通知
调整后的架构以下所示
这个方案上线后,先采用了主备两套 ES 集群流量比为 1:1,而后观察效果,发现查询 ES 的 t99 由以前的 10ms 降低到 5ms,降低大约 50%,在 Prometheus 中埋点展现以下
咱们对 ES 的读取仍是有待优化的地方,在 kibana 中经过观察 Search Profiler 发现 build_scorer 占用了大部分时间,接近 80%,以下所示
经过查询资料,发现能够把 mapping 文件中为 Integer 类型的映射字段改成 keyword 后能够提升性能,由于这些字段只有有限个值,而且查询时是经过 terms 精确匹配,因此定义为 keyword 后性能高些,至于性能高的根本缘由仍是须要深刻源码分析的,须要抽时间深刻研究。
而后咱们就改变 mapping 文件开始验证,上线后的效果对比图以下所示
可见上线后,效果仍是比较明显的
由于对 ES 底层不够了解,也只能经过问题驱动来一点点的优化,后面会深刻学习下 ES,再找能够优化的点
学无止境,若是文中哪里有问题,欢迎大佬批评指正,同时若是你有对 ES 优化有经验,也欢迎分享给我
https://www.jianshu.com/p/9830413f62eb
https://elasticsearch.cn/article/446
https://elasticsearch.cn/question/3253
https://www.elastic.co/cn/blog/searching-numb3rs-in-5.0
https://www.elastic.co/cn/blog/better-query-planning-for-range-queries-in-elasticsearch
欢迎关注公众号 【天天晒白牙】,获取最新文章,咱们一块儿交流,共同进步!