Elasticsearch原理

参考文献

Elasticsearch原理详解:https://blog.csdn.net/chuixue24/article/details/104022065

41张图了解Es原理:https://juejin.cn/post/6906430715731116045

Es中的概念介绍:https://juejin.cn/post/6908620596523827213#comment

Es全流程:https://juejin.cn/post/6972038748049670175

ElasticSearch原理知识点和整体结构详解:https://juejin.cn/post/6986480874137059341

Es方法论认知清单:https://mp.weixin.qq.com/s?__biz=MzI2NDY1MTA3OQ==&mid=2247484194&idx=1&sn=09fafbe34dc17a8bbe64919ac6be2662&chksm=eaa82b0adddfa21c8aa65b47f1c5b0a25c9ceaeb0ecc47055fd9c615d0f7a3fbfb6febee46e7&scene=21#wechat_redirect

原理涉及的概念

概念意义
Segment File分段,每个 Segment 事实上是一些倒排索引的集合
Commit将 Segment 合并,并写入磁盘
Commit Point记录着对每个 Segment 的操作
Translog提供所有还没有被刷到磁盘的操作的一个持久化纪录
Refresh刷新
Fsync刷磁盘,将 filesystem cache 中的所有 segment 刷新到磁盘的操作
Flush清理

Segment - 分段

Elasticsearch 存储的基本单元是 shard , ES 中一个 Index 可能分为多个 shard , 事实上每个 shard 都是一个 Lucene 的 Index ,并且每个 Lucene Index 由多个 Segment 组成, 每个 Segment 事实上是一些倒排索引的集合, 每次创建一个新的 Document , 都会归属于一个新的 Segment , 而不会去修改原来的 Segment ; 且每次的文档删除操作,会仅仅标记 Segment 中该文档为删除状态, 而不会真正的立马物理删除, 所以说 ES 的 index 可以理解为一个抽象的概念。es 每秒都会生成一个 segment 文件,当文件过多时 es 会自动进行 segment merge(合并文件),合并时会同时将已经标注删除的文档物理删除;

Commit - 提交

为了数据安全, 每次的索引变更都最好要立刻刷盘, 所以 Commit 操作意味着将 Segment 合并,并写入磁盘。保证内存数据尽量不丢。但刷盘是很重的 IO 操作, 所以为了机器性能和近实时搜索, 并不会刷盘那么及时。

Commit Point - 提交节点

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

Translog - 持久化纪录

translog 提供所有还没有被刷到磁盘的操作的一个持久化纪录。当 Elasticsearch 启动的时候, 它会从磁盘中使用最后一个提交点去恢复已知的段,并且会重放 translog 中所有在最后一次提交后发生的变更操作。为了防止 elasticsearch 宕机造成数据丢失保证可靠存储,es 会将每次的操作同时写到 translog 日志中。新文档被索引意味着文档会被首先写入内存 buffer ,操作会被写入 translog 文件。每个 shard 都对应一个 translog 文件;translog 会每隔 5 秒异步执行或者在每一个请求完成之后执行一次 fsync 操作,将 translog 从缓存刷入磁盘,这个操作比较耗时,如果对数据一致性要求不是跟高时建议将索引改为 async ,如果节点宕机时会有 5 秒数据丢失;

Refresh - 刷新

写入和打开一个新 segment 的轻量的过程,es 接收数据请求时先存入内存中,默认每隔一秒会从内存 buffer 中将数据写入 filesystem cache 中的一个 segment,内存 buffer 被清空,这个时候索引变成了可被搜索的,这个过程叫做 refresh;

Fsync - 刷磁盘

fsync 是一个 Unix 系统调用函数, 用来将内存 buffer 中的数据存储到文件系统. 这里作了优化, 是指将 filesystem cache 中的所有 segment 刷新到磁盘的操作;

Flush - 清理

es 默认每隔 30 分钟或者操作数据量达到 512mb ,会将内存 buffer 的数据全都写入新的 segment 中,内存 buffer 被清空,一个 commit point 被写入磁盘,并将 filesystem cache 中的数据通过 fsync 刷入磁盘,同时清空 translog 日志文件,这个过程叫做 flush;

数据写入过程 - 近实时搜索

提交(Commit)一个新的 segment 到磁盘需要一个 fsync 来确保 segment 被物理性地写入磁盘,这样在断电的时候就不会丢失数据。 但是 fsync 操作代价很大; 如果每次索引一个文档都去执行一次的话会造成很大的性能问题。我们需要的是一个更轻量的方式来使一个文档可被搜索,这意味着 fsync 要从整个过程中被移除。在 es 和磁盘之间是 filesystem cache 。 像之前描述的一样, 在内存缓冲区中的文档会被写入到一个新的段中。 但是这里新段会被先写入到文件系统缓存,这一步代价会比较低,稍后再被刷新(flush)到磁盘,这一步代价比较高。不过只要文件已经在 filesystem cache 中, 就可以像其它文件一样被打开和读取了。Lucene 允许新 segment 被写入和打开,使其包含的文档在未进行一次完整提交时便对搜索可见。 这种方式比进行一次提交代价要小得多,并且在不影响性能的前提下可以被频繁地执行。而 es 中底层搜索的此种方式基于 refresh ,refresh 的默认值是 1s ,所以搜索不是实时的,而是近实时。

image-20220228111626913

image-20220228104300210

一个 ElasticSearch 的 Shard 本质上是一个 Lucene Index

Lucene 是一个开源的,全文索引工具包。有 索引,搜索,分词 等功能,是 ElasticSearchApache Solr 的核心,它引入了按段(Segment)搜索的概念

相关入门资料:https://juejin.cn/post/7021683796747485214

image-20220228093737781

优化方案

写入优化

  • 使用bulk api批量操作

  • 调整refresh_interval的间隔,es在每一次refresh时都会创建lucene的segment,并尝试进行segment的合并,开销较大,若对搜索的实时性要求不高,可以适当的调大refresh_interval的大小

  • 不需要索引的字段指定index属性为not_analyzed

读取优化

  • 没有范围查找需求的number类型字段,类型定义为keyword

  • 慎用wildcard query,尽量使用分词后的结果使用match query,有使用wildcard query的需求,注意字符转义

  • 搜索词的长度要做限制

  • feed流场景使用search_after

  • 不需要得分的字段用filter context替换query content

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值