elasticsearch内部原理自我总结

35 篇文章 1 订阅
35 篇文章 1 订阅

环境

elasticsearch:5.5

自我理解

对于elasticsearch我自己也是新手,只是想做点笔记,记录下自己的理解。

我一直想明白当一个文档被索引进elasticsearch时,其内部干什么了?
本人结合网上的教程,记录下

倒排索引

一个新文档要使其可见,需要使用倒排索引,其长相如下:

词项文档1文档2文档3
中国XX
小米XXX
华为XX
南昌XX

有了倒排索引之后,新进的文档就可以被搜索到了。

注意:倒排索引被写入磁盘后是 不可改变 的:它永远不会修改。 不变性有重要的价值

①不需要锁。如果你从来不更新索引,你就不需要担心多进程同时修改数据的问题。
② 一旦索引被读入内核的文件系统缓存,便会留在哪里,由于其不变性。只要文件系统缓存中还有足够的空间,那么大部分读请求会直接请求内存,而不会命中磁盘。这提供了很大的性能提升。
③其它缓存(像filter缓存),在索引的生命周期内始终有效。它们不需要在每次数据改变时被重建,因为数据不会变化。
④写入单个大的倒排索引允许数据被压缩,减少磁盘 I/O 和 需要被缓存到内存的索引的使用量。
当然,一个不变的索引也有不好的地方。主要事实是它是不可变的! 你不能修改它。如果你需要让一个新的文档 可被搜索,你需要重建整个索引。这要么对一个索引所能包含的数据量造成了很大的限制,要么对索引可被更新的频率造成了很大的限制。

动态更新(倒排)索引

由于倒排索引具有不变性(一旦被写入磁盘就不能再改变),那么我们如何来实现更新倒排索引呢?官方的做法就是用更多的倒排索引。通过增加新的倒排索引来反应新近的修改,而不是重写整个倒排索引,毕竟重写整个倒排索引,要消耗巨大资源;每一个倒排索引都会被轮流查询到–从最早的开始–查询完后再对结果进行合并。

如果一个新文档立马就写入磁盘也会影响性能,所以新的文档首先被添加到内存索引缓存中,然后写入基于磁盘的段中,接着包含这个新段的提交点也会被写入磁盘,接着磁盘同步,把文件系统缓存中的文档刷新到磁盘,接着新段被打开,使其可以被搜索到,接着内存索引缓存被清空,等待接受新的文档。

这里写图片描述

注意

段其实就是倒排索引,其不能被改变。当文档发生改变时,每个提交点会包含一个.del文件,文件中会列出这些被删除文档的段信息。所以文档被删除时,并不会立马被删除,只是被标记了,其依然可以被搜索到,只不过在结果集返回前就已经移除了。

这里有一个新的问题就是磁盘同步是一件很消耗资源的事情,如果每次插入一个文档都去执行的话,就会造成很大的性能问题。这意味着我们再插入新文档时,不能立马就进行同步。

我们要知道在Elasticsearch和磁盘之间是文件系统缓存。
新文档 写入 内存索引缓存中,接着会写入到新段上,重点来了,这个新段不会直接写入磁盘而是先写入到文件系统缓存中,稍后才会写入到磁盘。只要文件已经在缓存中,就可以像其他文件一样被打开和读取了。

这里写图片描述

refresh

elasticsearch中,写入和打开一个新段(倒排索引)的轻量的过程叫做refresh。也就是把内存索引缓存中的数据写到新段的一个过程。由于elasticsearch默认每个分片是每秒自动刷新一次。这就造成其索引是近实时搜索而不是实时搜索。最长需要等待1秒。

目前处于性能考虑,我们文档还放在文件系统缓存中,如果不进行同步到磁盘的话,假设断电了,数据就丢失了。而由于上面也说明,同步不是实时的,是每个一段时间同步一次,默认是30分钟一次。假设elasticsearch9点同步过了,下次需要在9点半同步,而此时刚好断电了,这时内存里的数据就全部丢失了。但是我们又不想丢失掉。所以elasticsearch引入了translog或者叫事务日志。

那么其最终的流程就变成了:

1、一个文档被索引(插入)后,就会被添加到内存缓存区,并且追加到translog
2、分片默认是每秒刷新一次;即把内存缓存区里的数据刷新写入到新段中(文件系统缓存中),此时没有进行fsync(磁盘同步)。
3、这个新段会被打开并且使其可被搜索。
4、内存缓存区被清空。
5、这个进程会继续工作,更多的文档被添加进内容缓存区和追加事务日志。
6、这也就意味着每隔一段时间translog会变得越来越大。这时(倒排)索引被flush;与此同时一个新translog会被创建,并且一个全量提价被执行:
①所有在内存缓存区的文档都被写入到新段。
②缓存区被清空
③一个提交点被写入硬盘
④文件系统缓存通过fsync被刷新(flush
⑤老的translog被删除

translog 提供所有还没有被刷到磁盘的操作的一个持久化纪录。当 Elasticsearch 启动的时候, 它会从磁盘中使用最后一个提交点去恢复已知的段,并且会重放 translog 中所有在最后一次提交后发生的变更操作。

translog 也被用来提供实时 CRUD 。当你试着通过ID查询、更新、删除一个文档,它会在尝试从相应的段中检索之前, 首先检查 translog 任何最近的变更。这意味着它总是能够实时地获取到文档的最新版本。

flush

translog进行截断并进行提交的行为在elasticsearch中称作flush。分片每30分钟被自动刷新(flush),或者在 translog 太大的时候也会刷新。请查看 translog 文档 来设置,它可以用来 控制这些阈值。


这时其实还有个小问题,要是translog在断电之前还没有写入磁盘,这时,数据照样还是会丢失。默认情况下translog是每5秒fsync到磁盘或者在每次写请求完成之后。对于这种情况,官方说明:但是对于一些大容量的偶尔丢失几秒数据问题也并不严重的集群,使用异步的 fsync 还是比较有益的。


由于自动刷新refresh每秒创建一个段,这样就会造成短时间内,段数量暴增。而段数目太多会带来较大的麻烦。 每一个段都会消耗文件句柄、内存和cpu运行周期。更重要的是,每个搜索请求都必须轮流检查每个段;所以段越多,搜索也就越慢。
Elasticsearch通过在后台进行段合并来解决这个问题。小的段被合并到大的段,然后这些大的段再被合并到更大的段。

段合并的时候会将那些旧的已删除文档 从文件系统中清除。 被删除的文档(或被更新文档的旧版本)不会被拷贝到新的大段中。

启动段合并不需要你做任何事。进行索引和搜索时会自动进行。
1、 当索引的时候,刷新(refresh)操作会创建新的段并将段打开以供搜索使用。
2、 合并进程选择一小部分大小相似的段,并且在后台将它们合并到更大的段中。这并不会中断索引和搜索。

合并完成时的活动:

  • 新的段被刷新到了磁盘。
  • 写入一个提交点,该提交点包含新段且排除旧的和较小的段
  • 新的段被打开用来搜索
  • 老的段被删除

合并大的段需要消耗大量的I/O和CPU资源,如果任其发展会影响搜索性能。Elasticsearch在默认情况下会对合并流程进行资源限制,所以搜索仍然 有足够的资源很好地执行。

参考地址:
https://www.elastic.co/guide/cn/elasticsearch/guide/cn/merge-process.html
https://www.elastic.co/guide/en/elasticsearch/guide/current/making-text-searchable.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山鬼谣me

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值