搜索技术的秘密(一):概览

640?wx_fmt=jpeg

「多字段搜索」是一个非常复杂的话题,设想你有一堆日志记录,有很多字段。然后产品经理希望可以通过各种组合字段进行搜索,比如根据时间段、用户 ID、行为类型、目标 ID 等,得出满足条件的日志记录。

如果是单字段搜索,那很好办,把日志记到关系数据库中,在必要的字段上加索引就可以了。但是一旦涉及到复合条件查询,关系数据库会捉襟见肘。也许你会想到复合字段索引,这确实也是一种很好的解决方案,但是解决的能力也相对比较有限。在遇到复合字段搜索时,我们通常会借助于专业的搜索引擎,比如互联网领域广为使用的 Elasticsearch,本系列文章将会带读者一同潜入 ElasticSearch 的搜索技术,了解一下搜索领域的常用底层解决方案。

搜索引擎的最基础的技术就是倒排索引,它是关键词到文档列表的映射。给倒排索引提供一个原子的查询词汇,倒排索引可以得到与它相关的文档ID 列表。这个文档 ID 在本例中就是一条日志记录的主键 ID,通过这个主键 ID 就可以得到整条日志,这是因为搜索引擎除了倒排索引之外还会存储所有的日志记录,也就是日志 ID 到日志内容 Document 的映射。

class InvertedIndex {
  Map<String, List<Long>> key2docs;
}

class Documents<T> {
  Map<Long, T> docs;
}

在一个日志表上会有多个倒排索引,每个被搜索的字段都会生成一个倒排索引。这样当我们使用复合字段搜索时,通过每个倒排索引都会得到一个 文档ID 列表,然后对这多个文档ID 列表进行交集运算,就可以得到同时满足多个搜索条件的文档 ID 列表。这个交集运算算法也是搜索引擎的另一个重要的秘密之一,它对搜索性能的影响至关重要。

class Table<T> {
  Documents<T> docs;
  Map<String, InvertedIndex> field2Indexes;
}

我们的日志表内容和倒排索引不可能全部放在内存里,所以我们必须决定什么样的数据需要放在内存里,什么样的数据需要放在磁盘上。也许是简单的 LRU 算法,也许是背后有一个类似于 LevelDB 的存储引擎存储了所有的文档 ID 到文档内容,LevelDB 自己会决定哪些文档在内存里哪些文档在磁盘上,以及如何以最小化的 IO 代价拿到磁盘上的文档。如何降低内存又不会显著增加 IO 成本,这又是搜索引擎的又一个重难点之一。类似于 LevelDB 这样的存储引擎能帮我们搞定文档库大字典 docs 的存储,但是倒排索引跟文档库似乎又不太一样,单个 key 对应的文档 ID 列表可以非常长,如果将这个文档 ID 列表看成一个特殊的整体文档,那么这个整体文档会无比巨大,让他在内存里会消耗内存,让它在磁盘上频繁的序列化反序列化 IO 又会导致极高的 IO 成本。这也是一个无比头疼的问题,但是 Elasticsearch 有办法搞定它。

磁盘的成本固然低廉,但是如果使用普通的磁盘估计搜索引擎的效率也会大打折扣,因为搜索引擎不可避免会涉及到磁盘 IO,单次搜索往往会涉及到多次磁盘 IO。并发搜索进一步让磁盘的磁头繁忙的不可开销。所以对于 Elasticsearch,官方推荐的磁盘依然是 SSD,有了 SSD 磁盘,搜索性能就可以飞起来。如果没有 SSD,至少搜索引擎也是可用的,但是在高并发场景下可能会慢的让你咬牙切齿。

如果使用了昂贵的 SSD,那我们就必须考虑高效的磁盘存储。我们会使用一些特殊的压缩算法,以解决磁盘空间,同时呢又不能让解压缩算法拖慢搜索效率,因为解压缩的过程会涉及到 密集的 CPU 运算。这也是搜索技术的另一个重要当不必要的考虑点之一,尽可能地节约硬件成本。

既然搜索引擎是一个分布式系统,自然我们也不能只考虑单机的存储和计算,我们还需要面对的是它的分片、它的高可用这些复杂的话题。这里会涉及到分片算法、选举算法、查询分割、查询聚合等一系列高阶难题。我们还要搞定一系列网络故障,硬件故障,数据安全性等问题。

搜索引擎还要支持模糊查询,这就涉及到查询范围的扩大化、查询结果的相似度计算以及排序算法。就我们这些提及的讨论点来说,实现一个可用的易用的安全的搜索引擎有多难,而 Elasticsearch 搞定了这些,但是这世界上的搜索引擎非常之多,能够让 Elasticsearch 登顶了纳斯达克的原因不仅仅是这些技术上的因素,还有生态、服务、市场等我们作为程序员难以控制的范畴。这也超出了我的个人能力,在后面的系列文章中,我只会对 Elasticsearch 内部的技术点进行讨论,非技术因素恕我能力有限,互联网上也应该有非常多的文章在讨论 Elasticsearch 成功的秘诀,大家可以自行搜索。这一系列文章在形式上会自由散漫好一些,不会写的像掘金小册那样写的非常精细结构性非常强,有时候可能会为了图快完成任务而没有写的特别丰富多彩,出现一些细微的错误也在所难免,还请大家勇于指正。

下面是字节跳动的内推入口,找出自己心意的职位后,请勇于投递你的个人简历,内部系统的数据安全性做得非常到位,我是看不到你们的简历内容的,所以不必太担心个人隐私问题。北京、上海、深圳、杭州、成都、广州等城市的职位都有,Python、Java、Golang、算法、数据、分布式计算和存储的岗位也都有,个人发挥自己的搜商,进去自行寻找吧。

640?wx_fmt=png

老钱不需要你们的赞赏,投递自己简历就是对我最大的支持

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值