Elasticsearch 是一个分布式可扩展的实时搜索和分析引擎,一个建立在全文搜索引擎 Apache Lucene(TM) 基础上的搜索引擎。非常幸运的是,之前规划了很久的智能运输产品搜索与推荐在3个月前如期上线了,下面将分享下Elasticsearch 在业务系统中应用。
背景
一条运输产品是有提货(服务区域)报价、干线(地点到地点)报价、配送(服务区域)报价、路由、项目合同报价、服务区域(地图上一个不规则的区域)以及各种平台服务收费项等基础数据构成。而一个运输产品的生成是非常复杂的,它由各种线路成员的提+干+配组合构成、既包含了路由生成规则信息、也包含会员身份信息(有过滤)及平台规则(有过滤)。
服务区(多边形)针对长宁区画出来,mysql存储类型是geometry 。
运输产品的选择页面
它如何实现的呢?
主要是实时计算,通过发站-到站找到路由,再通过路由(如:上海-南京-厦门)产生的笛卡尔乘积(每段之间都有不同的线路成员的报价),每次动态计算要关联非常多张表,很多依赖系接口以及大量复杂的计算。
它也带来了很多的问题?
产品经理说:
- 选运输产品页面展示复杂,信息摆放错综杂乱,关键信息不突出
- 选运输产品页面前端逻辑复杂,每次优化牵一发动全身
- 产品未静态化,每次匹配拼装产品,影响性能,体验不好
- 产品配置功能实现单一,无法对交易场景进行配置,目前只是做了简单的配置并无限堆积,扩展性不强
开发者说:
- 查询速度慢,提配产品基于服务圈,耗时(无法缓存,命中率无限趋向于0)且难以排查问题;涉及大量复杂IO计算
- 未能抽象出一个完整的产品对象,无法分页问题;个性化较高(产品配置页面);用户身份以及大量个性化入参影响查询结果;动态产品会导致拿不到评价信息
- 交易后的运输产品快照,通过反推来展示繁琐
曾做过的优化
其实我们也进行过阶段性的优化
但这些优化还远远不够,任重道远!
预期
首先,进行基础数据的重塑
- 取消服务区域,可以按行政区域划分
- 统一报价阶梯,统一干线、配送产品的报价阶梯
- 价格对象,现在的价格对象没有调整价格的作用,而是现在的产品对象
最终目标
希望提高更丰富的搜索功能,为后续的产品推荐做准备。
争议点
1. 运输产品要不要静态化?
| 非静态化 | 静态化 |
优点 | 时效性较好 | 可以解决上面存在的大量问题 |
缺点 | 现有问题依然存在 | 但还是存在费用上繁杂上的计算,时效性有一定的延迟 |
可选的解决方案:
方案 | geometry | 图搜算法 | 全文搜索(更新) |
Neo4j | 不支持 | 非常丰富 | 不需要 |
高阶map-reduce | 继续使用mysql | 没有 | 不需要 |
es search | 支持 | 没有 | 支持 |
mongodb | 支持 | 没有 | 支持 |
2. 要不要静态化提配(服务区域)的信息?
关于提配的产品,由于该信息是基于用户坐标才能筛选出相关的产品,而静态化处理(不可能有坐标,就没有这块产品)会导致运输产品的链条不完整,如果这块业务不能接受按行政区域(非坐标),那就必须添加新的交互来解决它,这样徒增产品搜索的复杂度。
最终方案
最终业务上做了妥协,采用了静态化。静态化上我们采用全量(对现有数据进行全部迁移)+增量(对有变化数据及时更新)来保障es的数据完整性、准确性、时效性
组件图
设计方案
时序图(略,有敏感数据不展示)
物理拓扑图
在实践的过程中,我们也遇到了非常多的坑,下面将分享下我们这方面的经验。
坑1:Bin-log数据事件暴增问题
比如:一个用户在货运圈修改了“干线产品发布”中某些信息,从当前系统角度看,它是一个用户事件,而物理模型设计要满足数据库的范式(可能会分成很多表),这时候bin-log的master会把这些表的变动都推送过来。
解决方案:只关注主表的变动(从表的变动要映射到主表上)
坑2:关于评价及交易量的存储问题
由于评价是由评价系统针对整段运输产品定期生成的,时间上不确定性。
交易量是某一段(干线)触发统计的,时间上比较随机。
Es-search要不要存储及更新评价、交易量、折扣?如果要存的话,实时性只能是准实时:虑到整段运输产品数据量非常大,
评价评分:
解决方案:有变化就推送(匹配规则 key=inputKey)。
交易量:
解决方案:有变化就推送(匹配规则 key like %transLineId%)
解决方案2:从canal中读取并处理
折扣:
解决方案:目前无法确定增量范围,待定
坑3:定时任务效率不高
全量时太慢,采用elastic-job的任务分片
坑4:Canal高可用问题
目前只能提供单机服务问题
解决方案:运维做keepalive,目前官方没有很好的方案,故障最好的处理机制就是重启(应该重跑某一段时间内的增量),另外就是加强监控。
坑5:笛卡尔乘积批量太多导致elastic-search频繁超时
单个批量(5000条路由会产生100w种组合)太大操作bulk时不时的超时,参阅对应解决方法
坑6:保障ES实时性与一致性
关于实时性方面,业务接受允许一定的延迟(30s内),而一致性方面陆续采用很多幂等性设计比如业务乐观锁字段(order_state更新递增)、version 字段等。