倒排索引组成结构以及索引不可变原因

对于倒排索引是非常适合用来进行搜索的
它的结构:
(1)包含这个关键词的document list
(2)包含这个关键词的所有document的数量:IDF(inverse document frequency)
(3)这个关键词在每个document中出现的次数:TF(term frequency)
(4)这个关键词在这个document中的次序
(5)每个document的长度:length norm
(6)包含这个关键词的所有document的平均长度
其实本质上主要是为了计算相关度分数

_score = boost * idf * tf
此时boost = 2.2, idf = 0.18232156, tf = 0.5116279 idf = log( + (N - n + 0.5) / (n + 0.5))
此时n = (n, number of documents containing term),
N = (N, total number of documents with field) tf = freq / (freq + k1 * ( - b + b * dl / avgdl))
此时freq = (freq, occurrences of term within document),
k1 = 1.2(k1, term saturation parameter),
b = 0.75(b, length normalization parameter),
d1 = (dl, length of field),
avgdl = 5.5(avgdl, average length of field)

倒排索引的不可变好处

(1)不需要锁,提升了并发能力,避免锁的问题
(2)数据不变,一直保存在OS cache中,只要cache内存足够
(3)filter cache一直驻留在内存
(4)可以压缩,节省cpu和io开销
这个对应的就是primary shard的数量不变,不能修改field的属性(将date改成text)

倒排索引不可变的坏处

(1)每次都需要重新构建整个索引

document写入原理

(1)数据写入buffer
(2)commit point
(3)buffer中的数据写入新的index segment
(4)等待在OS cache中的index segment被fsync强制刷到磁盘上
(5)新的index segment被打开,供search使用
(6)buffer被清空

下面做几点说明:

1、在Elasticsearch中,底层用的是lucene,lucene底层的index是分为多个segment的,每个segment都会存放部分数据。
2、如果是删除操作,每次commit的时候,就会生成一个.del文件,标明哪个index segment的哪个document被删除了。
3、如果是更新操作,实际上是将的doc标记为deleted,然后将新的document写入新的index segment中。下次search过来的时候,也许会匹配到一个document的多个版本,但是之前的版本已经被标记为deleted了,所以只会返回最新版本的doc
4、如果搜索请求过来,在index segment中,匹配到了id=1的doc,此时会发现在.del文件中已经被标识为deleted了,这种数据就会被过滤掉,不会作为搜索结果返回。
图示如下:

写入流程近实时NRT(filesystem cache,refresh)

现有的流程的问题,每次都必须等待fsync将segment刷入磁盘,才能将segment打开供search使用,这样的话,从一个document写入,到它可以被搜索,可能会超过1分钟,这也就不是近实时的搜索了。主要的瓶颈在于fsync从磁盘IO写数据进磁盘是很耗时的。
ES写入流程的改进:
(1)数据写入buffer
(2)每个一定时间,buffer中的数据被写入segment文件,但是先写入OS cache
(3)只要segment写入OS cache,那就直接打开供search使用,不立即执行commit
数据写入OS cache,并被打开供搜索的过程,叫做refresh,默认是每隔一秒refresh一次,也就是说,每隔一秒就会将buffer中的数据写入OS cache中,写入一个新的index segment file。所以ES是近实时的,数据写入到可以被搜索,默认是1秒。
一般不用修改,让ES自己搞定就好了,要修改的话,通过refresh_interval参数即可
格式:

写入流程的实现 durability可靠存储(translog,flush)

最终流程:

()数据写入buffer缓存和translog日志文件
()每隔一秒,buffer中的数据被写入新的segment file,并进入os cache,此时segment被打开并供search使用
()buffer被清空
()重复1~,新的segment不断添加,buffer不断被清空,而translog中的数据不断累加
()当translog长度达到一定程度的时候,commit操作发生
(5.1)buffer中的所有数据,写入一个新的segment,并写入os cache,打开供使用
(5.2)buffer被清空
(5.3)一个commit point被写入磁盘,标明了所有的index segment
(5.4)filesystem cache中的所有index segment file缓存数据,被fsync强制刷到磁盘上
(5.5)现有的translog被清空,创建一个新的translog

translog

对Lucene的更改仅在Lucene提交期间持久保存到磁盘,这是一项相对昂贵的操作,因此无法在每次索引或删除操作后执行。如果进程退出或硬件发生故障,Lucene将在一次提交之后和另一次提交之前发生的更改将从索引中删除。

因为Lucene提交对于每个单独的更改都执行起来太昂贵,所以每个分片副本还有一个事务日志,称为与之关联的translog。所有索引和删除操作在由内部Lucene索引处理之后但在确认之前写入translog。在发生崩溃的情况下,最新的已确认但尚未包含在上一个Lucene提交中的事务可以在分片恢复时从translog中恢复。

Elasticsearch flush是执行Lucene提交并启动新的translog的过程。在后台自动执行刷新以确保translog不会变得太大,这将使得在恢复期间重放其操作需要相当长的时间。手动执行刷新的能力也通过API公开,尽管很少需要。

translog设置

translog中的数据仅在fsync编辑和提交translog时持久保存到磁盘 。如果发生硬件故障,自上次translog提交以来写入的任何数据都将丢失。

默认情况下,fsync如果index.translog.durability设置为async或request 在每个索引,删除, 更新或 批量请求结束时设置为(默认),则Elasticsearch会每隔5秒提交一次translog 。更确切地说,如果设置为request,则fsync在主数据库和每个已分配的副本服务器上成功编辑和提交translog之后,Elasticsearch将仅向客户端报告索引,删除,更新或批量请求的成功 。

以下可动态更新的每索引设置控制translog的行为:

index.translog.sync_interval
fsync无论写入操作 如何,translog都经常被写入磁盘并提交。默认为5s。小于的值100ms是不允许的。
index.translog.durability
是否fsync在每个索引,删除,更新或批量请求之后提交translog。此设置接受以下参数:
request
(默认)fsync并在每个请求后提交。如果发生硬件故障,所有已确认的写入都已提交到磁盘。
async
fsync并在每个背景中提交sync_interval。如果发生硬件故障,将丢弃自上次自动提交以来的所有已确认写入。
index.translog.flush_threshold_size
translog存储尚未安全保存在Lucene中的所有操作(即,不是Lucene提交点的一部分)。尽管这些操作可用于
读取,但如果要关闭并且必须恢复,则需要重新编制索引。此设置控制这些操作的最大总大小,以防止恢复时间
过长。达到最大大小后,将发生刷新,生成新的Lucene提交点。默认为512mb。
index.translog.retention.size
要保留的translog文件的总大小。保留更多的translog文件会增加在恢复副本时执行基于同步操作的机会。如
果translog文件不足,副本恢复将回退到基于文件的同步。默认为512mb
index.translog.retention.age
保留translog文件的最长持续时间。默认为12h。
PUT /my_index/_settings
{
"index.translog.durability": "async",
"index.translog.sync_interval": "5s"
}

图示如下:

数据恢复

假设os cache中囤积了一些数据,但是此时不巧,宕机了,os cache中的数据全部丢失,那么我们怎么进行数据恢复呢?
我们知道写doc的时候也会写入translog,那么translog就存储了上一次flush直到现在最近的数据变更记录。机器被重启之后,disk上的数据并没有丢失,此时就会将translog文件中的变更记录进行回收,重新执行之前的各种操作,在buffer中执行,在重新刷一个一个的segment到os cache中,等待下一次commit发生即可。

海量磁盘文件的合并(segment merge,optimize)

每秒一个segment file,会导致文件过多,而且每次search都要搜索所有的segment,很耗时。所以在Elasticsearch内部会默认在后台执行segment merge操作(forcemerge),在merge的时候,被标记为deleted的document也会被彻底物理删除掉。
每次merge的操作流程:
(1)选择一些有相似大小的segment,merge成一个大的segment
(2)将新的segment flush到磁盘上去
(3)写一个新的commit point,包括了新的segment,并且排除旧的那些segment
(4)将新的segment打开供搜索
(5)将旧的segment删除

POST /my_index/_optimize?max_num_segments=,尽量不要手动执行,让它自动默认执行就可以了

Elasticsearch由浅入深(十一)内核原理的更多相关文章

  1. 《Linux内核原理与设计》第十一周作业 ShellShock攻击实验

    <Linux内核原理与设计>第十一周作业 ShellShock攻击实验 分组: 和20179215袁琳完成实验及博客攥写 实验内容:   Bash中发现了一个严重漏洞shellshock, ...

  2. 2019-2020-1 20199329《Linux内核原理与分析》第十一周作业

    <Linux内核原理与分析>第十一周作业 一.本周内容概述: 学习linux安全防护方面的知识 完成实验楼上的<ShellShock 攻击实验> 二.本周学习内容: 1.学习& ...

  3. 2020-2021-1 20209307 《Linux内核原理与分析》第十一周作业

    这个作业属于哪个课程 <2020-2021-1Linux内核原理与分析)> 这个作业要求在哪里 <2020-2021-1Linux内核原理与分析第十一周作业> 这个作业的目标 ...

  4. Elasticsearch由浅入深(六)批量操作:mget批量查询、bulk批量增删改、路由原理、增删改内部原理、document查询内部原理、bulk api的奇特json格式

    mget批量查询 批量查询的好处就是一条一条的查询,比如说要查询100条数据,那么就要发送100次网络请求,这个开销还是很大的如果进行批量查询的话,查询100条数据,就只要发送1次网络请求,网络请求的 ...

  5. 《Linux内核原理与分析》第一周作业 20189210

    实验一 Linux系统简介 这一节主要学习了Linux的历史,Linux有关的重要人物以及学习Linux的方法,Linux和Windows的区别.其中学到了LInux中的应用程序大都为开源自由的软件, ...

  6. 20169207《Linux内核原理及分析》第十三周作业

    第一周作业::对Linux的基本知识进行了了解,并对基本操作进行熟悉和应用. 第二周作业::了解了冯诺依曼体系结构.各种寄存器的功能和汇编指令的作用和功能. 第三周作业::这周主要了解了Linux系统 ...

  7. 2017-2018-1 20179205《Linux内核原理与设计》第七周作业

    <Linux内核原理与设计>第七周作业 视频学习及操作分析 创建一个新进程在内核中的执行过程 fork.vfork和clone三个系统调用都可以创建一个新进程,而且都是通过调用do_for ...

  8. 2017-2018-1 20179209《Linux内核原理与分析》第七周作业

    一.实验 1.1task_struct数据结构 Linux内核通过一个被称为进程描述符的task_struct结构体来管理进程,这个结构体包含了一个进程所需的所有信息.它定义在linux-3.18.6 ...

  9. Elasticsearch 技术分析(九):Elasticsearch的使用和原理总结

    前言 之前已经分享过Elasticsearch的使用和原理的知识,由于近期在公司内部做了一次内部分享,所以本篇主要是基于之前的博文的一个总结,希望通过这篇文章能让读者大致了解Elasticsearch ...

  10. 2019-2020-1 20199303<Linux内核原理与分析>第二周作业

    2019-2020-1 20199303第二周作业 1.汇编与寄存器的学习 寄存器是中央处理器内的组成部份.寄存器是有限存贮容量的高速存贮部件,它们可用来暂存指令.数据和位址.在中央处理器的控制部件中 ...

随机推荐

  1. MicroPython:基于TPYBoard集合MAX7219点阵模块制作表白女神神器

    转载请注明文章来源,更多教程可自助参考docs.tpyboard.com,QQ技术交流群:157816561,公众号:MicroPython玩家汇 前言 又是一年毕业季,只有到了毕业季才会意识到自己又 ...

  2. conda opencv cv2.imshow无法使用

    error: -------src-dir-------/opencv-2.4.10/modules/highgui/src/window.cpp:501: error: (-2) The funct ...

  3. Spring Boot 2.0 快速集成整合消息中间件 Kafka

    欢迎关注个人微信公众号: 小哈学Java, 每日推送 Java 领域干货文章,关注即免费无套路附送 100G 海量学习.面试资源哟!! 个人网站: https://www.exception.site ...

  4. 关于 L3 缓存行 cacheLIne 的研究!还是对程序有举足轻重的作用!

    https://www.cnblogs.com/PurpleTide/archive/2010/11/25/1887506.html CLR via C# 读书笔记 2-3 Cache Lines a ...

  5. Flask笔记:cookie

    在网站中,HTTP请求是无状态的:第一次请求成功后,第二次请求时服务器依然不知道这次请求的所属用户是谁.为了解决这个问题,在第一次请求成功后,服务器会生成并返回对应的cookie信息给浏览器,而浏览器 ...

  6. MySQL问题记录——定义timestamp类型的数据

    MySQL问题记录——定义timestamp类型的数据 摘要:本文主要记录了在使用MySQL的过程中定义timestamp类型数据时遇到的问题以及解决方案. 问题重现 在Windows环境下安装MyS ...

  7. SVN每日定时备份脚本

    SVN每日定时备份脚本: @ECHO off REM SVN安装目录 SET SVN_HOME="D:\Program Files\VisualSVNServer" REM 版本库 ...

  8. Android实用的Toast工具类封装

    Toast这个提示框大家都晓得,显示一段时间后自动消失,不能获得焦点.但是在使用中有些问题: 1)需要弹出一个新的Toast时,上一个Toast还没有显示完2)可能重复弹出相同的信息3)Toast具体 ...

  9. HeadFirst设计模式---装饰者

    定义装饰者模式 装饰者模式动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案.这句话摘自书中,给人读得很生硬难懂.通俗地来说,装饰者和被装饰者有相同的父类,装饰者的行为组装着 ...

  10. Odoo 启动选项总结

    转载请注明原文地址:https://www.cnblogs.com/ygj0930/p/11189209.html 一:启动选项用在哪里 如果你是用Pycharm进行odoo二次开发的话,可以通过 R ...