标签:分配 建立 方式 接收 实时搜索 new replica code 强制
本篇我们来看看shard内部的一些操作原理,了解一下人家是怎么玩的。
倒排索引的结构,是非常适合用来做搜索的,Elasticsearch会为索引的每个index为analyzed的字段建立倒排索引。
倒排索引包含以下几个部分:
记录这些信息,就是为了方便搜索的效率和_score分值的计算。
倒排索引写入磁盘后就是不可变的,这样有几个好处:
前面提到倒排索引是基于不可变模式设计的,但实际Elasticsearch源源不断地有新数据进来,那光是建立、删除倒排索引,岂不是非常忙?
如果真是不停地建立,删除倒排索引,那ES压力也太大了,肯定不是这么实现的。ES通过增加新的补充索引来接收新的文档和修改的文档,而不是直接用删除重建的方式重写整个索引。
整个写入过程如下图所示:
index segment翻译过来叫"段",每秒会创建一个,ES把这个1秒内收到的、需要处理的文档都放在这个段里,可以把段认为是倒排索引的一个子集。
索引、分片、段的关系如下:
索引包含多个分片,每个分片是一个Lucene索引实例,一个分片下面有多个段。如果把分片看作是一个独立的倒排索引结构,那么这个倒排索引是由多个段文件的集合。
三者之间是包含关系:索引包含多个分片,分片包含多个段。
当文档被删除时,Commit Point会把信息记录在.del文件中,在.del文件中会标识哪些文档是有deleted标记的,但该文档还是存在于原先的index segment文件里,同样能够被检索到,只是在最终结果处理时,标记为deleted的文档被会过滤掉。
更新也是类似的操作,更新会把旧版本的文档标记为deleted,新的文档会存储在新的index segment中。
上面的流程细节的童鞋可以会发现,每次都需要fsync磁盘,数据才是可搜索的,那IO压力将特别大,耗费时间比较长,并且执行周期由操作系统控制,从一个新文档写入到可以被搜索,超过1分钟那是常有的事。
所以Elasticsearch对此做了一个改进:
index segment信息写入到os-cache中,即完成上面的第4步,该segment内的文档信息就可以被搜索到了。fsync操作就不立即执行了,
os-cache的写入代价比较低,最耗时的fsync操作交由操作系统调度执行。
上述的index segment写入到os-cache,并打开搜索的过程,叫做refresh,默认是每隔1秒refresh一次所以,es是近实时的,数据写入到可以被搜索,默认是1秒。
refresh的时间也可以设置,比如我们一些日志系统,数据量特别大,但实时性要求不高,我们为了优化资源分配,就可以把refresh设置得大一些:
PUT /music
{
"settings": {
"refresh_interval": "30s"
}
}
此参数需要在创建索引时使用,要注意一下的是除非有充分的依据,才会对refresh进行设置,一般使用默认的即可。
上述的写入流程当中,如果fsync到磁盘的操作没执行完成,服务器断电宕机了,可能会导致Elasticsearch数据丢失。Elasticsearch也设计了translog机制,跟关系型数据库的事务日志机制非常像,整个写入过程将变成这样:
这个执行一个提交并且归档translog的行为称作一次flush。分片每30分钟被自动刷新(flush),或者在 translog 太大的时候(默认512MB)也会刷新,当然也可以手动触发flush的执行,如下请求:
POST /music/_flush
但任其自动flush就够了。如果重启节点前担心会对索引造成影响,可以手动flush一下。毕竟节点重启后需要从translog里恢复数据,translog越小,恢复就越快。
translog写磁盘行为主要有两种,是由index.translog.durability配置项决定的:
如果系统不接受数据丢失,用translog同步方式,示例设置:
# 异步方式
PUT /music_new
{
"settings": {
"index.translog.durability": "async",
"index.translog.sync_interval": "5s"
}
}
# 同步方式
PUT /music_new
{
"settings": {
"index.translog.durability": "request"
}
}
Elasticsearch针对活跃的索引,每秒都会生成一个新的index segment,这些segment最终会以文件的形式存储在磁盘里,如果不对其进行处理,那么索引运用一段时间后,会有特别多的文件,零碎的文件太多了,也不是什么好事情,更耗费更多的文件资源,句柄等,搜索过程也会变慢。
Elasticsearch会在后台对segment进行合并,减少文件的数量,同时,标记为deleted的文档在合并时会被丢弃(delete请求只是将文档标记为deleted状态,真正的物理删除是在段合并的过程中),合并过程不需要人工干预,让Elasticsearch自行完成即可。
两个已经提交的段和一个未提交的段合并成为一个大的段文件
合并时会挑一些大小接近的段,合并到更大的段中,段合并过程不阻塞索引和搜索。
合并完成后,新的更大的段flush到磁盘中,并完成refresh操作,老的段被删除掉。
optimize命令可以强制合并API,并指定最终段的数量,如下命令:
POST /music_new/optimize
{
"max_num_segments": 1
}
指定segment最大数量为1,表示该索引最终只有一个segment文件。
本篇主要介绍shard内部的原理,包含写入、更新删除,translog机制,segment合并等,了解数据库的童鞋对translog机制应该非常熟悉,原理上大同小异,仅作抛砖引玉,谢谢。
标签:分配 建立 方式 接收 实时搜索 new replica code 强制
原文地址:https://www.cnblogs.com/huangying2124/p/12230177.html