内容简介:对于倒排索引是非常适合用来进行搜索的它的结构:(1)包含这个关键词的document list
倒排索引组成结构以及索引不可变原因
对于倒排索引是非常适合用来进行搜索的
它的结构:
(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(1 + (N - n + 0.5) / (n + 0.5)) 此时n = 2 (n, number of documents containing term), N = 2(N, total number of documents with field) tf = freq / (freq + k1 * (1 - b + b * dl / avgdl)) 此时freq = 1(freq, occurrences of term within document), k1 = 1.2(k1, term saturation parameter), b = 0.75(b, length normalization parameter), d1 = 4 (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
现有的流程的问题,每次都必须等待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参数即可
格式:
PUT /{index}
{
"settings": {
"refresh_interval": "1s"
}
}
图示如下:
写入流程的实现 durability可靠存储
最终流程:
(1)数据写入buffer缓存和translog日志文件
(2)每隔一秒,buffer中的数据被写入新的segment file,并进入os cache,此时segment被打开并供search使用
(3)buffer被清空
(4)重复1~3,新的segment不断添加,buffer不断被清空,而translog中的数据不断累加
(5)当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。
图示如下:
数据恢复
假设os cache中囤积了一些数据,但是此时不巧,宕机了,os cache中的数据全部丢失,那么我们怎么进行数据恢复呢?
我们知道写doc的时候也会写入translog,那么translog就存储了上一次flush直到现在最近的数据变更记录。机器被重启之后,disk上的数据并没有丢失,此时就会将translog文件中的变更记录进行回收,重新执行之前的各种操作,在buffer中执行,在重新刷一个一个的segment到os cache中,等待下一次commit发生即可。
海量磁盘文件的合并
每秒一个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删除
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- linux内核实时进程的调度原理
- 连接跟踪 (conntrack):原理、应用及 Linux 内核实现
- 内核必须懂(六): 使用kgdb调试内核
- Linux内核如何替换内核函数并调用原始函数
- Linux内核工程师是怎么步入内核殿堂的?
- Linux内核工程师是怎么步入内核殿堂的?
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Where Wizards Stay Up Late
Katie Hafner / Simon & Schuster / 1998-1-21 / USD 16.00
Twenty five years ago, it didn't exist. Today, twenty million people worldwide are surfing the Net. "Where Wizards Stay Up Late" is the exciting story of the pioneers responsible for creating the most......一起来看看 《Where Wizards Stay Up Late》 这本书的介绍吧!