我应该是公司第一个专职搜索的,当时搜索所有组件只有一个ES(elasticsearch),虽然之前在干过将近两年的solr,不过主要还是以数据检索为主(类似于为hbase建一个二级索引),既然组织安排也就接下了这口锅,从基础的查询解析/数据同步做起,一点点的把整个搜索的框架立起来,团队“一度扩张”到3个人,承接了整个公司大部分的搜索业务,负责的数据大概有几十亿,从第一年双十一忙于救火的状态到去年的平稳渡过,都不同程度证明了整个搜索团队的成长。
然而自团队成立初期业务和技术的爆发式增长之后,近大半年整个搜索团队都陷入了一种迷茫和疲惫的状态,大概来说可以归结以下几点:
- 20%搜索,80%数据
- 上手易,维护难
- 没有成就感
“20%搜索,80%数据”:这也是本文标题的来源,大部分业务对于搜索的需求其实很“轻量”,只要能保证搜索的准确和召回即可,而搜索引擎相当重要的排序则几乎没有需要,因为查询条件基本都会带上各式指定的排序条件。相对的,业务对一般来说搜索引擎相对弱势的实时性和数据一致性的要求却是相当的高要求;
“上手易,维护难”:最初设计搜索模块的时候大致分为三部分,查询分析优化(AS)/数据同步(Sync)/基础引擎(ES),每个模块都保持相互独立,经过几次重构之后,核心代码也相当精简,所以上手不难,难的是维护各个业务之间不同的数据同步和查询优化逻辑,业务变更经常会引发搜索逻辑的变更,不易维护;
“没有成就感”:这个是最威胁团队稳定和战斗力的,轻量的搜索需要和重度的数据依赖导致我们不得不疲于应对各项业务,日常工作的大部分时间都陷入了业务泥潭,搜索需要提升的数据一致性/分词/ES换代/搜索权重分计算框架优化等等都被挂起,虽然每天看起来很忙,但是一天工作结束之后没有多少成就感,也无法感受到快乐工作。
就如同中医治病讲究疏导,破局也得找出团队问题症结所在,年底一段时间,我几乎每晚都在反思,总结了几点:
- 存储数据结构化
- 搜索查询结构化
- 数据同步问题定位回路过长
- 数据一致性和实时性要求高
“存储数据结构化”:大多数业务存储在搜索的数据相当结构化,基本就是组合mysql的几张表形成一张持久化的view;
“搜索查询结构化”:大多数查询都可以用sql来表达,并没有太多rank定制;
“数据同步问题定位回路过长”:数据同步的流程可以表示为
{业务=>mysql=>binlog=>producer=>mq=>consumer=>es=>业务}
数据流转的回路都是分散在若干个技术组,其中业务负责将数据写入db,而搜索负责consumer到es,所以一旦最终从es获取数据出现不一致或者延迟,我们要定位问题需要横跨若干技术组,还需要业务配合操作mysql,上面每个步骤都可能有数据丢失,加上mq会导致的数据乱序覆盖问题,简直是个灾难;
“数据一致性和实时性要求高”:就如前面提到,搜索数据其实相当于一个持久化的mysql view,业务对于数据一致性和实时性的要求非常高,但是业务却无法感知整个数据同步过程,甚至是否真的同步到了ES都无法感知。
如同物种进化的物竞天择,技术也是需要主动适应应用场景的变化,否则只能衰败然后淘汰,既然了解了业务场景,那么就需要相应的改变我们原有的技术架构和数据流:
- 存储和查询都相当结构化,那就把ES当作DB来用
- 数据同步回路太长,那就通过同步调用来同步数据
另外补充一下:其实ES和Solr一直都有在DB排行上出现。
破局之道:
- 从服务层沉到数据层,通过标准接口与业务解耦
- 保证从接口到ES的数据准确,让业务回归同步回路
- 只介入重度依赖rank的搜索业务(搜索的本职)
通过标准接口,屏蔽ES原本的rest接口和tcp接口中相对复杂的逻辑,降低业务接入门槛;细粒度的接口,让业务更加灵活的组合应用;业务接入,可以让数据同步过程更加健康,因为业务会比我们更加清楚需要的数据;同步调用,可以让业务实时感知数据是否正常到达ES。
当有了这些组件,搜索平台就很自然的浮出水面了,剩下的就是将平台还未完整的服务补全,提供一套UI供业务自助服务(建索引/删减字段/索引管理/审核/可视化查询)。
到目前为止,搜索平台的后端服务已经上线了2个月了,支撑着搜索同步的一大半数据流量,其它业务也正在逐步迁移当中;UI管理也已经开发至alpha4版本,准备推出公测了。