ES近实时搜索原理

关系图:
image.png

Segment(段):Lucene里面的一个数据集概念
提交点文件:有一个列表存放着所有已知的所有段
ES底层是基于Lucene,最核心的概念就是Segment(段),每个段本身就是一个倒排索引。
ES中的Index由多个段的集合和commit point(提交点)文件组成。

提交点文件中有一个列表存放着所有已知的段,下面是一个带有1个提交点和3个段的Index示意图:


image.png

Doc新增提交主要过程如下:
一、写入磁盘后可见:
1、Doc写入Buffer
Doc会先被搜集到内存中的Buffer内,这个时候还无法被搜索到,如下图所示:


image.png

2、 Doc Commit
每隔一段时间,会将buffer提交,在flush磁盘后打开新段使得搜索可见,详细过程如下:

(1)创建一个新段,作为一个追加的倒排索引,写入到磁盘(文件系统缓存)
(2)将新的包含新段的Commit Point(提交点)写入磁盘(文件系统缓存)
(3)磁盘进行fsync,主要是将文件系统缓存中等待的写入操作全部物理写入到磁盘,保证数据不会在发生错误时丢失
(4)这个新的段被开启, 使得段内文档对搜索可见
(5)将内存中buffer清除,又可以把新的Doc写入buffer了
下面展示了这个过程完成后的段和提交点的状态:


image.png

通过这种方式,可以使得新文档从被索引到可被搜索间的时间间隔在数分钟,但是还不够快。因为磁盘需要fsync,这个就成为性能瓶颈。我们前面提到过Doc会先被从buffer刷入段写入文件系统缓存(很快),那么就自然想到在这个阶段就让文档对搜索可见,随后再被刷入磁盘(较慢)。
二、写入磁盘前可见:
ES写入原理流程图.png

Commits in Lucene

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

Translog

新文档被索引意味着文档会被首先写入内存 buffer 和 translog 文件。每个 shard 都对应一个 translog 文件。


translog.png

Refresh in Elasticsearch

在 elasticsearch 中, _refresh操作默认每秒执行一次,意味着将内存 buffer 的数据写入到一个新的Segment 中,这个时候索引变成了可被检索的。


refresh.png

Flush in Elasticsearch

Flush操作意味着将内存buffer的数据全都写入新的Segments中,并将内存中所有的Segments全部刷盘,并且清空translog日志的过程。


flush.png

1、refresh:
Lucene支持对新段写入和打开 - 可以使文档在没有完全刷入硬盘的状态下就能对搜索可见,而且是一个开销较小的操作,可以频繁进行。
下面是一个已经将Docs刷入段但还没有完全提交的示意图:


image.png

我们可以看到,新段虽然还没有被完全提交,但是已经对搜索可见了。
这种对新段的巧妙操作过程被称为refresh,默认执行的时间间隔是1秒,这就是ES被称为近实时搜索的原因。

2、translog
为了避免在两次commit操作间隔时间发生异常导致Doc丢失,ES中采用了一个事务日志记录每次对ES的操作。加上translog后新增文档流程如下:
文档被添加到buffer同时追加到translog,如图:


image.png

进行refresh操作,清空buffer,文档可被搜索但尚未flush到磁盘。translog不会清空,如图:
image.png

继续步骤1的过程:
每隔一段时间(例如translog变得太大),index会被flush到磁盘,新的translog文件被创建,这个commit完整执行结束。在这个操作后,会发生以下事件:
(1)所有内存中的buffer会被写入新段
(2)buffer被清空
(3)一个提交点被写入磁盘
(4)文件系统缓存通过fsync flush
(5)之前的旧translog被删除

下面示意图展示了这个状态:


image.png

3、translog的作用
(1)通过前文描述我们知道translog其实就记录了还尚未被flush到磁盘的操作。当 Elasticsearch 启动的时候, 它会从磁盘中使用最后一个提交点去恢复已知的段,并且会重放 translog 中所有在最后一次提交后发生的变更操作。
translog 也被用来提供实时 CRUD 。当你试着通过ID来RUD一个Doc,它会在从相关的段检索之前先检查 translog 中最新的变更。
(2)translog的安全性
默认translog是每5秒或是每次请求完成后被fsync到磁盘(在主分片和副本分片都会)。也就是说,如果你发起一个index, delete, update请求写入translog并被fsync到主分片和副本分片的磁盘前不会返回200状态。
这样会带来一些性能损失,可以通过设为异步fsync,但是必须接受由此带来的丢失少量数据的风险:
PUT /my_index/_settings
{
    "index.translog.durability": "async",
    "index.translog.sync_interval": "5s"
}

4、flush
flush就是执行commit清空、干掉老translog的过程。默认每个分片30分钟或者是translog过于大的时候自动flush一次。可以通过flush API手动触发,但是只会在重启节点或关闭某个索引的时候这样做,因为这可以让未来ES恢复的速度更快(translog文件更小)。
三、 ES对Doc删除的处理
(1)删除一个ES文档不会立即从磁盘上移除,它只是被标记成已删除。因为段是不可变的,所以文档既不能从旧的段中移除,旧的段也不能更新以反映文档最新的版本。
ES的做法是,每一个提交点包括一个.del文件(还包括新段),包含了段上已经被标记为删除状态的文档。所以,当一个文档被做删除操作,实际上只是在.del文件中将该文档标记为删除,依然会在查询时被匹配到,只不过在最终返回结果之前会被从结果中删除。ES将会在用户之后添加更多索引的时候,在后台进行要删除内容的清理。
(2)Doc删除与段合并的关系
通过每秒自动刷新创建新的段,用不了多久段的数量就爆炸了,每个段消费大量文件句柄,内存,cpu资源。更重要的是,每次搜索请求都需要依次检查每个段。段越多,查询越慢。
ES通过后台合并段解决这个问题。ES利用段合并的时机来真正从文件系统删除那些version较老或者是被标记为删除的文档。被删除的文档(或者是version较老的)不会再被合并到新的更大的段中。
ES对一个不断有数据写入的索引处理流程如下:
索引过程中,refresh会不断创建新的段,并打开它们。
合并过程会在后台选择一些小的段合并成大的段,这个过程不会中断索引和搜索。合并过程如图:


image.png

两个已提交的段 和一个未提交的段合并为一个更大的段。从上图可以看到,段合并之前,旧有的Commit和没Commit的小段皆可被搜索。
(3)段合并后的操作:
a、新的段flush到硬盘
b、编写一个包含新段的新提交点,并排除旧的较小段。
c、新的段打开供搜索
d、旧的段被删除
合并完成后新的段可被搜索,旧的段被删除,如下图所示:


image.png

四、Doc更新
文档的更新操作和删除是类似的:当一个文档被更新,旧版本的文档被标记为删除,新版本的文档在新的段中索引。该文档的不同版本都会匹配一个查询,但是较旧的版本会从结果中删除。

注:
什么情况下要强制刷新:
1、reindex后,手动修改refresh,由-1(不刷新)改为想要的刷新值
2、在读多,写少时,可以强制不刷新,因为每写入一条数据就会产生一个新段,查询时就会查一次,降低效率
3、即时性要求高,:如广告立马需要被看到,需要手动强制刷新

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容