ES分布式搜索引擎的故事


前言

我们每天都会用到搜索引擎,那么,思考几个问题:输入“2020年美国大选结果是啥?”后,

  • 搜索引擎如何从海量数据中,以一种可以接受的延迟将最优的结果展现出来?
  • 海量的数据是如何存储的,原理是什么?
  • 对于大选新闻,如何实时的发布,让用户能搜索到?

一、故事的开始:搜索中的“飞花令”——倒排索引

小时候,老师提问《山居秋暝》,小李子很快能够想到:

空山新雨后,天气晚来秋。

明月松间照,清泉石上流。

竹喧归浣女,莲动下渔舟。

随意春芳歇,王孙自可留。

长大了,小李子去参加中国诗词大会,董卿问,包含流的诗句,,,当场懵逼了。

为什么很容易就能够根据题目想到整首诗,却很难根据诗中某个内容,想到整首诗?
从专业角度来讲,是因为大脑中建立了 《山居秋暝》–> 诗 的索引,而没有 流 --> 诗 的索引。

搜索引擎为什么快,是因为它也做了索引

这时候就会有人问,那这索引怎么做?岂不是诗中的每个字都要指向这首诗,也就是这首诗要做40个索引??

显然,我们有更好的办法,即对于一个汉字,可以指向多首诗。例如,对于流

  • 流 --> 《山居秋暝》、《于北平作》、《春日望海》……

这就是倒排索引

要想真正的理解ES中的倒排索引,还要了解ES中的基本概念。

ES基本概念

ES是一个基于Luncene开发的开源分布式搜索引擎

许多年前,一个刚结婚的名叫 Shay Banon 的失业开发者,跟着他的妻子去了伦敦,他的妻子在那里学习厨师。 在寻找一个赚钱的工作的时候,为了给他的妻子做一个食谱搜索引擎,他开始使用 Lucene 的一个早期版本。

直接使用 Lucene 是很难的,因此 Shay 开始做一个抽象层,Java 开发者使用它可以很简单的给他们的程序添加搜索功能。 他发布了他的第一个开源项目 Compass。

后来 Shay 获得了一份工作,主要是高性能,分布式环境下的内存数据网格。这个对于高性能,实时,分布式搜索引擎的需求尤为突出, 他决定重写 Compass,把它变为一个独立的服务并取名 Elasticsearch。

第一个公开版本在2010年2月发布,从此以后,Elasticsearch 已经成为了 Github 上最活跃的项目之一,他拥有超过300名 contributors(目前736名 contributors )。 一家公司已经开始围绕 Elasticsearch 提供商业服务,并开发新的特性,但是,Elasticsearch 将永远开源并对所有人可用。

据说,Shay 的妻子还在等着她的食谱搜索引擎…​

核心术语

  1. ES中的核心:索引、文档、字段,和数据库中的概念相对应
  • 索引 --> 表
  • 文档 --> 行
  • 字段 --> 列
  1. Mapping:处理es中数据的方式和规则

  2. 近实时NRT:从索引一个文档到该文档能被搜索到只有一个轻微的延迟(1s内)
  3. 集群、结点、分片、分段后文会讲

倒排索引

为什么ES搜索效率比数据库的正排索引快?

  • tire 字典树

    对于数据库中的查询,是通过key-value,每个key都是唯一的。
    而在lucene4.x之前,采用的是tire的数据结构,它能够共享前缀,例如,对于英文的26字母,A开头的就以A为前缀开始查,这样查询的效率大大提升,并且空间也大大缩小
  • tire的不足
    tire只能共享前缀,其实还可以共享后缀——FST(Finite State Tranducer)有限状态转换器。

对于cat、deep、do、dog、dogs的存储结构
(查看网址:http://examples.mikemccandless.com/fst.py?terms=&cmd=Build+it%21

FST可以将原字典压缩3-20倍,相对于HashMap,FST可以压缩到9-60分之一的大小,虽然FST的千万级别数据查询效率会比HashMap慢10倍,但是它的大小可以让他在内存中运行,抵消掉了时间上的不足。

倒排索引不变性:索引写入磁盘后不会改变

  • 不需要锁,不必担心同步问题
  • 可被内核的文件系统缓存,停留在内存中,大部分请求会直接请求到内存,不会落到磁盘上
  • filter缓存,在索引的生命周期始终有效。不需要再每次数据改变时重建
  • 写入单个较大的倒排索引使允许数据被压缩

二、“飞花令”的冠军——自顶向下介绍ES集群、读写原理

很遗憾,由于小李子的脑子装不下那么多诗,所以与冠军“擦肩而过”。
同样,我们的一台服务器是不可能装下那么多数据的,所以就要做集群。在这一部分我们要探索ES的集群、分片、备份、分段

ES集群、读写概览

1. 集群

一个ES集群可以有多个计算机结点,每个结点里面包含分片(主分片)和备份(副分片)

在ElasticSearch Head中新建索引时,要设置分片和副分片,这里的5和1的含义是:

  • 创建5个分片,负载到集群中的所有机器
  • 每个主分片都有一个副分片

    注意点:每个主分片的内容和副分片的内容是完全一致的,所以主副分片不能放在同一台机器上

我这里把第二台机器关掉了,所以它的副分片就没地方放,相当于只做了主分片,没有副分片。

1.1 扩展

当新增了一个计算机结点会发生什么?

  • 索引中的所有分片会自动均匀分布在所有结点
  • 因此,原集群中的分片,会部分迁移到新结点上
1.2 容灾

  • 当挂掉了一个结点,副分片直接升级为主分片

2. 文档写

  • 随机选取一个结点作为协调结点
  • 由协调结点进行文档路由并将内容转发到要写入的主分片
  • 由主分片进行数据同步,更新到副分片
  • 最后返回客户响应

3. 文档读

  • 随机选取协调结点
  • 找到主分片或副分片进行轮循读取
  • 响应给客户

4. 分片越多越好吗???

  • 每个索引和分片都会产生一定的资源开销
  • 索引、映射、状态信息存储在集群状态中
  • 分片中的一部分数据要保存在内存
  • 在单个结点中要尽量存储更多数据

考虑深度分页的情况:查询从9999开始的十条数据(有三个分片,每个上面存有10w条数据)

它并不是从每个分片中选出10个然后合并30个再从30中选10个。
而是

  • 每个分片选9999+10=10009个
  • 三个分片中合并为30027个
  • 再从里面选10个

所以,首先分片过多,会造成分页的性能下降
其次,深度分页这个伪需求会造成性能的极大浪费

ES集群内部原理

  • 集群:可以理解为部署了多台机器,所有机器的群体
  • 分片(shard):就是把索引库(对应数据库一个表)拆分为多份(把数据表中的数据拆分为多个片段),每份就是一个分片
  • 备份(replica):除了不能作为协调结点(coordinating node),其他的功能和主分片完全相同
  • 分段:可以根据业务来理解,对于一个新的商品信息的插入,正常情况是以当前时间来作为updateTime的,我们就可以根据分段来处理新增的数据是否要索引。假如我们设定的时间为2020.1.1,而我们人为的插入一条updateTime为2019.10.10的数据,那么,这条数据不会进行索引,用户自然就查不到。

1. 新增数据-动态更新索引

上文提到,索引创建后就不可变,那么如何新增数据呢?——新建索引
索引如何被新建?

  1. 新文档收集到内存索引缓存——>插入新数据先进缓存
  2. 缓存提交
    • 新段(包含这个新增数据的索引)写入磁盘
    • 包含新段名字的提交点写入磁盘
    • 磁盘进行同步,确保缓存数据刷到磁盘
  3. 将新段开启,让全文可见,可被搜索
  4. 内存缓存清空,等待接受新文档

2. 删除数据——段合并

在上面的过程中,每次回新建一个段,而每个段都会消耗一定的内存和CPU,当新增多个数据,会导致段的数量增多。因此,ES后端会对段进行合并。
新段关闭用来搜索,老段直接删除。
对于要删的文档,最初只是标记了删除,但在物理机上还存在,在进行段合并的时候,对于要删除的数据,才去除,不合并。

3. 近实时搜索

在上面的动态更新索引中已经谈到,新段创建后是存在缓存中的。这时候,为了提高检索效率,就已经可以被搜索,并不需要等到全部提交。


到此,我们解决了数据存储、实时发布的问题。
接下来我们要解决查询过程中如何筛选,如何将最优的信息放在最前面


三、身为观众,我有百度——ES中的数据分析

此时的我正在电视机前看中国诗词大会总决赛,紧张激动的飞花令又来了,董卿出了个“流”字,身为观众,我有百度,所以,我搜了个:“包含流字的诗句有哪些?”,百度果然没让我失望

很明显,我只用点开第一个链接就能获取到我所要的内容。
那么,百度是如何将数据从那么多的索引中筛选出来,并作出排序?

1. 分析

ES中存在一个叫分析器的东西,它由三个模块组成,我们以“包含流字的诗句有哪些?”为例

  • 字符过滤器:过滤、转换掉标点符号,介词等。这里会过滤掉“?”、“的”
  • 分词器:将语句中的单词进行拆分。不同的分词器有不同的规则
    • 包含
    • 诗句
    • 哪些
  • 分词过滤器:大小写转换、停用词、同义词转换
    • 包含 --> 带有、含有
    • 诗句 --> 诗词、古诗



项目中用到了elasticsearch-analysis-ik作为中文分词器

2. 打分

上面的分析是对于输入的,在展现给用户之前,要进行打分排序,找到最优结果。

  • TF-IDF(词频-逆文档频率) 算法
    字词的重要性随着它在文件中出现的次数成正比增加,同时会随着在语料库中的频率成反比下降。
    缺点:会受文章的长短影响,当文章长时,它里面出现的词的次数也会相增加。
  • Okapi BM25(Best Match25)算法

    ES6开始采用BM25算法

总结与思考

这篇文章基本上解决了以下几个问题

真正的搜索引擎远不止于此,如果对现有的知识做出的搜索引擎进行优化,我觉得:

  • 可以对实时热点数据进行缓存,减少查询负载(例如美国大选)
  • 减少分页数,靠后的那些分页可以直接舍弃不必存储
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Elasticsearch是一个基于开源的分布式搜索和分析引擎,主要用于处理大规模数据的实时搜索、分析和存储。它利用了分布式架构的优势,可以快速地搜索和处理海量数据。 Elasticsearch具有高度的可伸缩性,可以水平扩展以适应不断增长的数据量。它使用了分片和复制机制,将索引数据划分为多个分片,并在集群中的多个节点上进行复制,从而实现了数据的分布式存储和冗余备份。 对于搜索功能,Elasticsearch采用了倒排索引的概念,它通过建立字典来映射每个词项到包含该词项的文档,以实现快速的全文搜索。同时,它还支持各种查询类型和过滤器,可以根据不同的需求进行高级搜索和过滤。 此外,Elasticsearch还提供了灵活的数据分析功能,可以进行聚合、统计和数据可视化等操作。它内置了强大的聚合框架,可以对数据进行复杂的分组、求和、平均等操作,以便更好地理解和分析数据。 另外,Elasticsearch还支持实时索引和搜索,可以实时地从更新的数据中搜索和获取结果。它采用了近乎实时的索引策略,可以保证数据的低延迟和高吞吐量。 总结来说,Elasticsearch作为一款分布式搜索和分析引擎,具有高可伸缩性、快速的搜索和分析能力,可以帮助用户高效地处理大规模数据,并从中获取有用的信息和洞察。它广泛应用于各个领域,如企业搜索、日志分析、数据挖掘等。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值