elasticsearch实践篇: 智能运输产品

Elasticsearch 是一个分布式可扩展的实时搜索和分析引擎,一个建立在全文搜索引擎 Apache Lucene(TM) 基础上的搜索引擎。非常幸运的是,之前规划了很久的智能运输产品搜索与推荐在3个月前如期上线了,下面将分享下Elasticsearch 在业务系统中应用。

背景

一条运输产品是有提货(服务区域)报价、干线(地点到地点)报价、配送(服务区域)报价、路由、项目合同报价、服务区域(地图上一个不规则的区域)以及各种平台服务收费项等基础数据构成。而一个运输产品的生成是非常复杂的,它由各种线路成员的提+干+配组合构成、既包含了路由生成规则信息、也包含会员身份信息(有过滤)及平台规则(有过滤)。

服务区(多边形)针对长宁区画出来,mysql存储类型是geometry

elasticsearch实践篇: 智能运输产品_第1张图片

运输产品的选择页面

elasticsearch实践篇: 智能运输产品_第2张图片

它如何实现的呢?

主要是实时计算,通过发站-到站找到路由,再通过路由(如:上海-南京-厦门)产生的笛卡尔乘积(每段之间都有不同的线路成员的报价),每次动态计算要关联非常多张表,很多依赖系接口以及大量复杂的计算。

elasticsearch实践篇: 智能运输产品_第3张图片

它也带来了很多的问题?

产品经理说:

  1. 选运输产品页面展示复杂,信息摆放错综杂乱,关键信息不突出
  2. 选运输产品页面前端逻辑复杂,每次优化牵一发动全身
  3. 产品未静态化,每次匹配拼装产品,影响性能,体验不好
  4. 产品配置功能实现单一,无法对交易场景进行配置,目前只是做了简单的配置并无限堆积,扩展性不强

开发者说:

  1. 查询速度慢,提配产品基于服务圈,耗时(无法缓存,命中率无限趋向于0)且难以排查问题;涉及大量复杂IO计算
  2. 未能抽象出一个完整的产品对象,无法分页问题;个性化较高(产品配置页面);用户身份以及大量个性化入参影响查询结果;动态产品会导致拿不到评价信息
  3. 交易后的运输产品快照,通过反推来展示繁琐

曾做过的优化

其实我们也进行过阶段性的优化

elasticsearch实践篇: 智能运输产品_第4张图片

elasticsearch实践篇: 智能运输产品_第5张图片

elasticsearch实践篇: 智能运输产品_第6张图片

但这些优化还远远不够,任重道远!

预期

首先,进行基础数据的重塑

  1. 取消服务区域,可以按行政区域划分
  2. 统一报价阶梯,统一干线、配送产品的报价阶梯
  3. 价格对象,现在的价格对象没有调整价格的作用,而是现在的产品对象

elasticsearch实践篇: 智能运输产品_第7张图片

最终目标

希望提高更丰富的搜索功能,为后续的产品推荐做准备。

elasticsearch实践篇: 智能运输产品_第8张图片

争议点

1. 运输产品要不要静态化?

 

非静态化

静态化

优点

时效性较好

可以解决上面存在的大量问题

缺点

现有问题依然存在

但还是存在费用上繁杂上的计算,时效性有一定的延迟

可选的解决方案:

方案

geometry

图搜算法

全文搜索(更新)

Neo4j

不支持

非常丰富

不需要

高阶map-reduce

继续使用mysql

没有

不需要

es search

支持

没有

支持

mongodb

支持

没有

支持

2. 要不要静态化提配(服务区域)的信息?

关于提配的产品,由于该信息是基于用户坐标才能筛选出相关的产品,而静态化处理(不可能有坐标,就没有这块产品)会导致运输产品的链条不完整,如果这块业务不能接受按行政区域(非坐标),那就必须添加新的交互来解决它,这样徒增产品搜索的复杂度。

最终方案

最终业务上做了妥协,采用了静态化。静态化上我们采用全量(对现有数据进行全部迁移)+增量(对有变化数据及时更新)来保障es的数据完整性、准确性、时效性

组件图

elasticsearch实践篇: 智能运输产品_第9张图片

设计方案 

elasticsearch实践篇: 智能运输产品_第10张图片

elasticsearch实践篇: 智能运输产品_第11张图片

elasticsearch实践篇: 智能运输产品_第12张图片

时序图(略,有敏感数据不展示)

物理拓扑图

elasticsearch实践篇: 智能运输产品_第13张图片

在实践的过程中,我们也遇到了非常多的坑,下面将分享下我们这方面的经验。

坑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 字段等。

你可能感兴趣的:(最新,elasticsearch,搜索技术)