搜索引擎还能如此简单

内容纲要

为啥用搜索

众所周知,我们平时接触到的网页或者app,看到或者在线体验到的东西,背后都是由一个个服务接口组成,通过服务接口完成数据的写入和展示;

在我们日常开发的服务接口中,大部分接口能用图中这个简单模式即可完成,但在一些数据量大或者TPS很高的场景下,数据库的查询就成了瓶颈,这个模型开始面临很多挑战;

  1. 锁等待;由于热点数据高频读写,锁竞争激烈,导致整个数据库的读写性能明显下降,最终用户难以接受漫长的等待,从而放弃这次糟糕的体验;
  2. 大表关联;在数据量膨胀后,即使数据更新的不多,但用户的一次访问需要取到多个大表之间关联后的结果数据,通常关系数据库都会加索引,但是平均每次关联查询仍是漫长的等待,则迫切的需要新的数据获取方式解决这个痛点;
  3. 模糊查询;通常一个网页或者系统都需要提供一个搜索框,让用户进来不会感到迷茫,用户会在搜索框中输入关心的内容,此时,作为服务提供者的我们,不知道用户到底关系的哪一块的数据,只能把可能的几个数据字段都提供模糊查询,如果这个时候的模糊查询功能用数据库来完成,显然这个处理时间,用户也是难以接受的;

搜索为啥快

快和慢都是一个相对的概念,搜索的快是对比关系数据库而得到的结论;我们这里拿搜索的lucene和关系数据库的mysql来对比;

  • 首先第一点,两者从设计的方向和目标就有很大区别;mysql强调数据的关系,按行存储,多版本控制协议(MVCC)和锁的存在保证了整体的事务,可以满足各种复杂的逻辑,但同时带来的就是之前提到的锁的问题和执行效率的问题,在一定程度上牺牲了可用性,保障了CAP中的一致性(C)和分区容错性(P);lucene强调快速检索,按列存储,在数据之间关系的表达上显得略有欠缺,所以需要尽可能的提前将关系处理后组成一张“宽表”,虽然在lucene索引提交上也有多版本控制协议(MVCC),但在与源数据的同步上略有延迟,在数据一致性(C)上做了一定的牺牲,保证了可用性(A)和分区容错(P);从这一点比较下来,没锁的肯定比有锁的快;
  • 第二点,就是行存储和列存储的差异;即使查找少数的几个属性,但由于这些目标数据埋藏在各行数据单元中,而行单元往往又特别大,应用程序必须读取每一条完整的行记录从而使得读取效率大大降低对此,mysql给出的优化方案是用innerdb引擎加“索引”,但随着数据量的膨胀和查询需求的日渐复杂,这个解决方案也开始力不从心,此时lucene的列存储优势就凸显了出来,每一列单独查找,将每一列查到的文档号做聚合,最后给到完整的数据,在查询列变多时,查询性能也不会明显下降;
  • 第三点,就是两者的索引区别;mysql中常用的innerdb引擎为考虑读写性能平衡,采用B+树存储数据,先通过查找到B+树上的主键信息,再到磁盘上拿出完整的数据;lucene则是倒排索引,将每个属性的所有值拿出来,用值对应主键id的结构存放,采用FST高效压缩算法,将数据集中的所有列的所有值压缩到内存中,查询时,通过值的匹配拿到主键id结果集;随着数据量和查询属性的增多,两者查询的效率成两极分化;

一个搜索接口的诞生

在分析完搜索的优势和特点后,我们应该如何利用搜索的能力,解决我们实际应用中一个个查询场景的性能问题呢?
先来看下搜索的模型;

基于这个模型,可以概括搜索做两件事情:

1.数据同步
2.提供查询

所以,一个搜索接口的开发流程如下:

  1. 定义搜索引擎表结构;一个搜索接口最关键和最重要的一步,就是将这个接口承载业务中的数据关系整理出来,常见的比如:医生搜索接口,以医生表为主体,关联医生所在医院表信息,患者信息等,其中的一对一或者一对多都需要明确,以便搜索字段中的类型选择;其过程就是整理数据实体中的对应关系,最后将这个对应关系中的多个表扁平化,最后形成一张“宽表”;
  2. 全量的数据写入;简单的说,就是把这个业务对应的数据整理到一起,复制一份到搜索引擎中存储,所以一般做法是通过SQL查询,将数据库中多个表的数据分别查出来,拼接为“宽表”的结构提交到搜索引擎构建;
  3. 定时的数据同步;此时若数据库中有数据更新,为性能考虑,一般会配置定时更新任务,将单位时间段内更新的数据,批量查出来更新到搜索引擎;
  4. 准实时的数据同步;若在一些状态变更等数据敏感度较高的场景,通过监听数据库binlog消费变更数据消息,完成数据准实时更新,或者提供数据更新接口,主动调用接口将数据实时更新,在非必要情况下,一般定时更新能满足的需求就不用搞实时更新,因为实时更新的策略对搜索性能还是有一定损耗的;
  5. 封装搜索引擎API,提供索引数据的查询服务;

批量搜索接口的生产

根据上面的流程,可以看出,一个搜索接口需要:

1.整理业务数据实体的关系
2基于关系整理出数据同步SQL
3.基于修改时间给出定时更新的SQL
4.实时链路配置或者索引更新接口
5.可供查询的搜索服务接口

在了解整个开发流程后,是否有更高效的搜索接口开发效率?为了提效,我们提出一个目标:

将以上流程所需的SQL和字段配置化,自动同步数据,并且有灵活高效的搜索接口可以直接服务

基于这个目标,微医搜索云平台的诞生了,支持两个核心能力:

基于配置,自动同步数据
支持所有的搜索功能特性

作为业务方,想用到搜索的能力,只需要关注自己业务的逻辑和整理出数据关系的SQL即可将这个复杂查询任务转换为高效查询的搜索接口!
所以,想要接入这个平台,你只需要提供:

  • 取名;为接口定义一个名字,并作为数据写入和查询的票据;
  • 整理数据SQL;将列表中用到的字段和表之间的关系,用SQL表达出来;
  • 指定字段类型;平台提供基于SQL自动提取字段,但字段类型,是否分词需要指明;

以上核心的3个步骤,一个搜索接口即诞生;
目前搜索云平台可以支持的功能:
数据同步方面:

多表跨库的数据关联
定时更新和实时更新配置
提供接口更新索引
多值和动态类型字段配置

查询方面的功能:

多维度模糊查询
自定义排序和过滤
支持自定义得分公式排序加权
支持自定义字段统计和分组
支持地理位置范围查询
支持关键词高亮

发展的方向

随着业务的发展,关系数据库显然不是数据源存储的唯一载体;作为搜索云平台,目标就是追求CAP的同时,兼容多个异构数据源,成为各大数据查询的核心出口;

One thought on “搜索引擎还能如此简单”

发表评论

邮箱地址不会被公开。 必填项已用*标注