博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
搜索技术的秘密(一):概览
阅读量:2440 次
发布时间:2019-05-10

本文共 2331 字,大约阅读时间需要 7 分钟。

640?wx_fmt=jpeg

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

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

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

class InvertedIndex {  Map
> key2docs;}class Documents
 {  Map
 docs;}

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

class Table
 {  Documents
 docs;  Map
 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

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

转载地址:http://lvbqb.baihongyu.com/

你可能感兴趣的文章
java.lang.UnsatisfiedLinkError: no jacob in java.library.path
查看>>
getWriter() has already been called for this response
查看>>
java 自动获取广播地址
查看>>
Integer.valueOf(String) 方法之惑
查看>>
Exception之The valid characters are defined in RFC 7230 and RFC 3986
查看>>
servlet 重定向传参数过长导致界面空白没反应 ,服务器使用的是tomcat
查看>>
No compiler is provided in this environment. Perhaps you are running on a JRE rather than a JDK
查看>>
SQL面试题之行列转换
查看>>
基于restful的协议
查看>>
vim /etc/profile 写入时 出现 E121:无法打开并写入文件解决方案
查看>>
FastJson解析内部类的实例时报错:No default constructor for entity
查看>>
分布式数据库系统概述
查看>>
top命令
查看>>
mv命令
查看>>
PL/SQL数组 一
查看>>
阿里巴巴公司DBA笔试题 二
查看>>
Linux专题
查看>>
Installing Oracle9i 32-bit on Red Hat 9, 8.0, 7
查看>>
ORACLE面试题 一
查看>>
使用Opatch工具应用过渡性Patch
查看>>