美文网首页
ElasticSearch原理

ElasticSearch原理

作者: 不知名的蛋挞 | 来源:发表于2020-02-27 15:03 被阅读0次

ES生成倒排索引和搜索数据机制

ES中,所有的文档在存储之前都要首先进行分析。用户可根据需要定义如何将文本分割成token、哪些token应该被过滤掉,以及哪些文本需要进行额外处理等等。

下面给出一个生成倒排索引的例子。

  • 索引名:article
  • 字段名:title
  • 搜索内容:Select * from article where title like ‘%搜索引擎%’

【文档】

文档ID 文档内容
1 ES是最流行的搜索引擎
2 Java是世界上最流行的语言
3 搜索引擎是如何诞生的

【文档 -> 单词词典】

单词词典:词词典是由文档集合中出现过的所有单词构成的字符串集合。单词词典内每条索引项记载单词本身的一些信息以及指向“倒排列表”的指针。

单词 文档ID列表
ES 1
最流行 1,2
搜索引擎 1,3
Java 2
世界 2
语言 2
如何 3
诞生 3

【单词词典 -> PostingList】

PostingList:倒排列表记录了单词对应的文档信息集合。每条记录称为一个倒排项。倒排项包括:文档id、单词频率(TF,Term Frequency)、位置(Postion)、偏移(Offset )。

DocId TF Postion Offset
1 1 2 <7,11>
3 1 0 <0,4>

所有单词的倒排列表往往顺序地存储在磁盘的某个文件里,这个文件被称之为倒排文件。倒排文件是存储倒排索引的物理文件。

ES节点结构

分片(Shard)

ES的分片机制可将一个索引内部的数据分布地存储于多个节点。

Shard有两种类型:primary和replica,即主shard及副本shard。

  • Primary shard用于文档存储,每个新的索引会自动创建5个Primary shard,此数量可在索引创建之前通过配置自行定义,不过,一旦创建完成,其Primary shard的数量将不可更改。
  • Replica shard是Primary Shard的副本,用于备份数据及提高搜索性能。
    每个Primary shard默认配置了一个Replica shard,但也可以配置多个,且其数量可动态更改。ES会根据需要自动增加或减少这些Replica shard的数量。

ES集群可由多个节点组成,各Shard分布式地存储于这些节点上。ES可自动在节点间按需要移动shard,例如增加节点或节点故障时。

片段( segment )

ElasticSearch中的每个分片包含多个segment,每一个segment都是一个倒排索引;在查询的时,会把所有的segment查询结果汇总归并后最为最终的分片查询结果返回。

  1. 每个分片包含多个“分段”。每个分段是一个倒排索引。
  2. 默认每秒都会生成一个segment文件。
  3. 分段内的doc数量上限是2的31次方。

ES的CRUD

(1)ES写数据过程

  1. 客户端向Node1 发送索引写文档请求。
  2. Node1 根据文档ID(_id字段)计算出该文档应该属于shard0,然后请求路由到Node3的P0分片上。
  3. Node3在P0上执行了请求。如果请求成功,则将请求并行的路由至Node1,Node2的R0上。
  4. 当所有的Replicas报告成功后,Node3向请求的Node(Node1)发送成功报告,Node1再报告至Client。
  5. 当客户端收到执行成功后,操作已经在Primary shard和所有的replica shards上执行成功了。

写请求分片ID计算方法:shard = hash(routing) % number_of_primary_shards
routing默认是文档ID,可自定义。

由于上面的路由规则,主分片数量不可变

ES写数据底层原理:

  1. 先写入内存 buffer,在 buffer 里的时候数据是搜索不到的。同时将数据写入 translog 日志文件。
  2. 重复上面的步骤,新的数据不断进入 buffer 和 translog,不断将 buffer 数据写入一个又一个新的 segment file 中去。每次 refresh 完 buffer 清空,translog 保留。
  3. 随着这个过程推进,translog 会变得越来越大。当 translog 达到一定长度的时候,就会触发 commit 操作。
  4. buffer 快满了,或者到一定时间(默认是每隔 1 秒钟),就会将 buffer 中现有数据 refresh 到 os cache 中去,清空 buffer。
  5. 将一个 commit point写入磁盘文件,里面标识着这个 commit point 对应的所有 segment file。将一个 commit point写入磁盘文件,里面标识着这个 commit point 对应的所有 segment file。
  6. 最后清空 现有 translog 日志文件,重启一个 translog,此时 commit 操作完成。
  7. 默认 30 分钟自动执行一次 flush,但如果 translog 过大,也会触发 flush。

translog 日志文件的作用是什么?

  1. 保证在 cache中的数据不会因为elasticsearch重启或者宕机的时候丢失。
  2. 当系统重启时会从translog中恢复之前记录的操作。

(2)ES查询过程

读操作步骤(根据文档id查询):

  1. 客户端发送Get请求到NODE1。
  2. NODE1使用文档的_id决定文档属于shard0。shard0的所有分片位于所有3个节点上。这次,它将请求路由至NODE2。
  3. NODE2将文档返回给NODE1,NODE1将文档返回给客户端。

ES读数据底层原理:

  1. 客户端发送请求至对应文档的shard。
  2. 先在filesystem cache中进行获取。
  3. 如果不存在,再到对应segment的磁盘文件中寻找。
  4. 找到之后,数据缓存进filesystem cache。
  5. 通过shard返回给客户端。
  1. 对于读请求,请求节点(NODE1)将在每次请求到来时都选择一个不同的replica shard来达到负载均衡。使用轮询策略轮询所有的replica shards。
  2. 读请求可以从 primary shard 或 replica shard 读取,采用的是随机轮询算法。
  3. 写请求是写入 primary shard,然后同步给所有的 replica shard。

(3)ES更新过程

  1. 客户端发送更新操作请求至NODE1。
  2. NODE1将请求路由至P0所在的NODE3。必须是Primary shard所在的位置。
  3. NODE3从P0读取文档,改变source字段的JSON内容,然后试图重新对修改后的数据在P0做索引。
  4. 如果NODE3成功更新了文档,它将并行的将新版本的文档同步到NODE1和NODE2的replica shards重新建立索引。
  5. 一旦所有的replica shards报告成功,NODE3向被请求的节点(NODE1)返回成功,然后NODE1向客户端返回成功。

如果此时这个文档已经被其他的进程修改了,那么它将重新执行3步骤,这个过程如果超过了retryon_conflict设置的次数,就放弃。

ES索引字段主要属性配置

index属性

  • analyzed:分词后索引,可搜索。
  • not_analyzed:字段值不分词,以单个关键词进行索引。
  • no:字段不索引,当然也就不能搜索。

store属性

属性store默认false,当某个数据字段很大,我们可以指定其它字段store为true,这样就不用从_source中取数据。

_source 是源文档,当你索引数据的时候, elasticsearch 会保存一份源文档到 _source ,如果文档的某一字段设置了 store 为 true,这时候会在 _source 存储之外再为这个字段独立进行存储。

这么做的目的主要是针对内容比较多的字段,放到 _source 返回的话,因为_source 是把所有字段保存为一份文档,命中后读取只需要一次IO,包含内容特别多的字段会很占带宽影响性能,通常我们也不需要完整的内容返回(可能只关心摘要),这时候就没必要放到 _source 里一起返回了(当然也可以在查询时指定返回字段)。

相关文章

网友评论

      本文标题:ElasticSearch原理

      本文链接:https://www.haomeiwen.com/subject/zlgthhtx.html