【搜索引擎】3-ES读写读取过程和原理,倒排索引介绍

avatar 2020年11月23日21:48:15 5 3098 views
博主分享免费Java教学视频,B站账号:Java刘哥

先简单说一下过程,再说原理

一、ES写入数据过程

1、客户端随机选择一个 node 发送请求,这个 node 就是 coordinating node(协调节点)

2、coordinating node 对 document 进行路由,将请求转发到该索引的 primary shard 的 node 上

3、primary shard 所在的 node 处理请求,存储数据,然后把数据同步到它的 replica shard 上

4、 coordinating node 发现 primary shard 和 所有 replica shard 都同步了数据,就返回响应结果给客户端

 

 

二、ES读取数据过程

这里指的是根据 document 的 id 直接查询,对 id 进行 hash(), 判断 document 在哪个 shard 上,然后去那个 shard 查询。

1、客户端随机选择一个 node 发送请求,这个 node 就是 coordinating node(协调节点)

2、coordinating node 对 id 进行哈希路由,定位 document 在 哪个 primary shard 的 node 上

3、然后负载均衡会在 primary shard 和 replica shard 中随机选一个,返回数据给 coordinating node

4、coordinating node 再返回数据给客户端

 

三、ES搜索关键字过程

比如搜索一个关键字

1、客户端随机选择一个 node 发送请求,这个 node 就是 coordinating node(协调节点)

2、coordinating node 将搜索请求发送到所有 shard (从 primary shard 或 replica shard负载均衡搜索)

3、查询阶段:每个 shard 将结果(document的id)返回给协调节点,由协调节点进行合并、排序和分页等操作,产生最终结果

4、拉取数据阶段:协调节点根据id去各个节点拉取实际的 document 数据,最终返回给客户端

 

四、ES写入数据底层详细原理

网上找的一张图,侵删

 

1、核心概念

segment file: 存储倒排索引的文件,每个segment本质上就是一个倒排索引,每秒都会生成一个segment文件,当文件过多时es会自动进行segment merge(合并文件),合并时会同时将已经标注删除的文档物理删除

 

commit point(重点理解): 记录当前所有可用的segment,每个commit point都会维护一个.del文件,即每个.del文件都有一个commit point文件(es删除数据本质是不属于物理删除),当es做删改操作时首先会在.del文件中声明某个document已经被删除,文件内记录了在某个segment内某个文档已经被删除,当查询请求过来时在segment中被删除的文件是能够查出来的,但是当返回结果时会根据commit point维护的那个.del文件把已经删除的文档过滤掉

 

translog日志文件: 为了防止elasticsearch宕机造成数据丢失保证可靠存储,es会将每次写入数据同时写到translog日志中(图中会有详解)。

 

os cache:操作系统里面,磁盘文件其实都有一个东西,叫做os cache,操作系统缓存,就是说数据写入磁盘文件之前,会先进入os cache,先进入操作系统级别的一个内存缓存中去

 

2、 写数据的过程

1)先写入buffer,在buffer里的时候数据是搜索不到的同时将数据写入translog日志文件

 

2)如果buffer快满了,或者到一定时间,将buffer里的数据写入到 os cache 中,然后再写入到新的 segment file,这个过程叫 refresh。

 

每隔1秒钟,es将buffer中的数据写入一个新的segment file,每秒钟会产生一个新的磁盘文件,segment file,这个segment file中就存储最近1秒内buffer中写入的数据

但是如果buffer里面此时没有数据,那当然不会执行refresh操作咯

只要buffer中的数据被refresh操作,刷入os cache中,就代表这个数据就可以被搜索到了。

 

3)只要数据进入os cache,此时就可以让这个segment file的数据对外提供搜索了。

 

4)重复1~3步骤,新的数据不断进入buffer和translog,不断将buffer数据写入一个又一个新的segment file中去,每次refresh完buffer清空,translog保留。随着这个过程推进,translog会变得越来越大。当translog达到一定长度的时候,就会触发commit操作。

 

5)commit操作发生第一步,就是将buffer中现有数据refresh到os cache中去,清空buffer

 

6)将一个commit point写入磁盘文件,里面标识着这个commit point对应的所有segment file

 

7)强行将os cache中目前所有的数据都fsync到磁盘文件中去

 

translog日志文件的作用是什么?就是在你执行commit操作之前,数据要么是停留在buffer中,要么是停留在os cache中,无论是buffer还是os cache都是内存,一旦这台机器死了,内存中的数据就全丢了。

 

所以需要将数据对应的操作写入一个专门的日志文件,translog日志文件中,一旦此时机器宕机,再次重启的时候,es会自动读取translog日志文件中的数据,恢复到内存buffer和os cache中去。

 

commit操作:1、写commit point;2、将os cache数据fsync强刷到磁盘上去;3、清空translog日志文件

 

8)将现有的translog清空,然后再次重启启用一个translog,此时commit操作完成。默认每隔30分钟会自动执行一次commit,但是如果translog过大,也会触发commit。整个commit的过程,叫做flush操作。我们可以手动执行flush操作,就是将所有os cache数据刷到磁盘文件中去。

 

不叫做commit操作,flush操作。es中的flush操作,就对应着commit的全过程。我们也可以通过es api,手动执行flush操作,手动将os cache中的数据fsync强刷到磁盘上去,记录一个commit point,清空translog日志文件。

 

9)translog其实也是先写入os cache的,默认每隔5秒刷一次到磁盘中去,所以默认情况下,可能有5秒的数据会仅仅停留在buffer或者translog文件的os cache中,如果此时机器挂了,会丢失5秒钟的数据。但是这样性能比较好,最多丢5秒的数据。也可以将translog设置成每次写操作必须是直接fsync到磁盘,但是性能会差很多。

 

 

 

倒排索引

在搜索引擎中,每个文档都有一个对应的文档 ID,文档内容被表示为一系列关键词的集合。例如,文档 1 经过分词,提取了 20 个关键词,每个关键词都会记录它在文档中出现的次数和出现位置。

那么,倒排索引就是关键词到文档 ID 的映射,每个关键词都对应着一系列的文件,这些文件中都出现了关键词。

举个栗子。

有以下文档:

DocId Doc
1 谷歌地图之父跳槽 Facebook
2 谷歌地图之父加盟 Facebook
3 谷歌地图创始人拉斯离开谷歌加盟 Facebook
4 谷歌地图之父跳槽 Facebook 与 Wave 项目取消有关
5 谷歌地图之父拉斯加盟社交网站 Facebook

对文档进行分词之后,得到以下倒排索引

WordId Word DocIds
1 谷歌 1,2,3,4,5
2 地图 1,2,3,4,5
3 之父 1,2,4,5
4 跳槽 1,4
5 Facebook 1,2,3,4,5
6 加盟 2,3,5
7 创始人 3
8 拉斯 3,5
9 离开 3
10 4
.. .. ..

另外,实用的倒排索引还可以记录更多的信息,比如文档频率信息,表示在文档集合中有多少个文档包含某个单词。

那么,有了倒排索引,搜索引擎可以很方便地响应用户的查询。比如用户输入查询 Facebook,搜索系统查找倒排索引,从中读出包含这个单词的文档,这些文档就是提供给用户的搜索结果。

要注意倒排索引的两个重要细节:

  • 倒排索引中的所有词项对应一个或多个文档;
  • 倒排索引中的词项根据字典顺序升序排列

上面只是一个简单的栗子,并没有严格按照字典顺序升序排列。

 

  • 微信
  • 交流学习,有偿服务
  • weinxin
  • 博客/Java交流群
  • 资源分享,问题解决,技术交流。群号:590480292
  • weinxin
avatar

发表评论

avatar 登录者:匿名
匿名评论,评论回复后会有邮件通知

  

已通过评论:0   待审核评论数:0