对于索引分片数量,我们一般在模板中统一定义,在数据规模比较大的集群中,索引分片数一般也大一些,在我的集群中设置为 24。但是,并不是所有的索引数据量都很大,这些小数据量的索引也同样有较大的分片数。在 elasticsearch 中,主节点管理分片是很大的工作量,降低集群整体分片数量可以降低 recovery 时间,减小集群状态的大小。很多时候,冷索引不会再有数据写入,此时,可以使用 shrink API 缩小索引分配数。缩小完成后,源索引可删除。

shrink API 是 es5.0之后提供的新功能,他并不对源索引进行操作,他使用与源索引相同的配置创建一个新索引,仅仅降低分配数。由于添加新文档时使用对分片数量取余获取目的分片的关系,原分片数量是新分片倍数。如果源索引的分片数为素数,目标索引的分片数只能为1.

我们跟随一个例子,分析缩小过程。

准备源索引

创建索引: my_source_index,5个主分片,1个副分片,并写入几条测试数据

通过下面的命令,将索引标记为只读,且所有分片副本都迁移到名为node-idea的节点上。

注意,“所有分片副本”不指索引的全部分片,无论主分片还是副分片,任意一个就可以。分配器也不允许将主副分片分配到同一节点。

1
2
3
4
5
6
7
8
9
10
 
curl -XPUT 'localhost:9200/my_source_index/_settings?pretty' -H 'Content-Type: application/json' -d'
{
  "settings": {
    "index.routing.allocation.require._name": "node-idea",
    "index.blocks.write": true
  }
}
'
 

选项:
index.blocks.write
设置为 true 来禁止对索引的写操作。但索引的 metadatra 可以正常写。

缩小索引

执行shrink:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
 
curl -XPOST 'localhost:9200/my_source_index/_shrink/my_target_index?pretty' -H 'Content-Type: application/json' -d'
{
  "settings": {
    "index.number_of_replicas": 1,
    "index.number_of_shards": 1,
    "index.codec": "best_compression"
  },
  "aliases": {
    "my_search_indices": {}
  }
}
'
 

这将创建含义一个主分片和一个副分片的目的索引:my_target_index

恢复原索引写操作
 
PUT /source_index/_settings
 
{
 
"settings": {
 
"index.blocks.write": false
 
}
 
}

shrink 工作过程

引用官方手册对 shrink 工作过程的描述:

  • First, it creates a new target index with the same definition as the source index, but with a smaller number of primary shards.
  • Then it hard-links segments from the source index into the target index. (If the file system doesn’t support hard-linking, then all segments are copied into the new index, which is a much more time consuming process.)
  • Finally, it recovers the target index as though it were a closed index which had just been re-opened.

创建新索引

第一点,使用旧索引的配置创建新索引,新索引的 shard 同样需要与源索引一样,所有副本都分配到相同节点,否则无法执行硬链接

创建硬链接

从源索引到目的索引创建硬链接。如果操作系统不支持硬链接,就拷贝lucene 分段。

在 linux 下通过 strace 命令跟踪硬链接创建过程,能清晰看到内部过程:

图中基本信息
JYglvWRnSqmNgA3E1CahZw 为源索引
RvDP65d-QD-QTpwOCaLWOg 为目的索引
_0.cfe,_0.si,_0.cfs 类型的文件为 lucene 编号为 0 的 segment,编号依次类推

链接过程
从源索引的 shard[0] 开始,遍历所有 shard,将所有 segment 链接到目的索引,目的索引的 segment 从 0 开始命名,依次递增。在本例中,由于源索引的 shard[0] 没有数据,因此从 shard[1] 开始链接

为什么一定要硬链接,不使用软链接?
文件系统由两部分组成,inode 和 block。block用于存储用户数据,inode 用于记录元数据,系统通过 inode 定位唯一的文件。
硬链接:文件有相同的 inode 和 block
软链接:文件有独立的 inode 和 block,block 内容为目的文件路径名
那么为什么一定要硬链接过去呢?如果软链接过去,删除源索引,目的索引的数据也会被删除,硬链接则不会。满足下面条件时操作系统才真正删除文件:

文件被打开的 fd 数量为0且硬链接数量为0

使用硬链接,删除源索引,只是将文件的硬链接数量减1
由于使用了硬链接,也因为硬链接的特性带来一些限制:不能交叉文件系统或分区进行硬链接的创建,因为不同分区和文件系统有自己的 inode。

不过,既然都是链接,shrink 完成后,修改源索引,目的索引会变吗?答案是不会。虽然链接到了源分段,shrink 期间索引只读,目标索引能看到的只有源索引的当前数据,shrink 完成后,由于 lucene 中分段的不变性,源索引新写入的数据随着 refrensh 会生成新分段,而新分段没有链接,在目标索引中是看不到的。如果源索引进行 merge,源分段被删除,硬链接数量减1,目标索引仍然不受影响。因此,shrink 完毕后最终的效果就是,两个索引的数据看起来是完全独立的

目的索引 recovery

经过链接过程之后,主分片已经就绪了,副分片还是空的,通过 recovery 将主分片数据拷贝到副分片。recovery 如何触发的?就是通过内部对索引的_close 再_open 操作

事实上,硬链接也是走的 recovery 流程,下面看一下相关实现代码

硬链接过程源码分析

硬链接过程在目标索引 my_target_index 的恢复流程中,入口:IndexShard#startRecovery,有下列几中类型的recovery:

  • EXISTING_STORE 主分片从 translog恢复
  • PEER 副分片从主分片远程拉取
  • SNAPSHOT 从快照恢复
  • LOCAL_SHARDS 只有 shrink 用到?

此时的恢复类型为 LOCAL_SHARDS,执行 storeRecovery.recoverFromLocalShards在 addIndices中,调用 lucene 中的 org.apache.lucene.store.HardlinkCopyDirectoryWrapper实现硬链接。

addIndices 将整个源索引的全部 shard 链接到目标路径。

1
2
3
 
addIndices(RecoveryState.Index indexRecoveryStats, Directory target, Directory... sources)
 

本例中源索引由5个分片,sources 的值为:

1
2
3
4
5
6
7
 
0 = "(store(mmapfs(/V/idea/nodes/0/indices/-Puacb8gSQG4UAvr-vNopQ/0/index)))"
1 =  "(store(mmapfs(/V/idea/nodes/0/indices/-Puacb8gSQG4UAvr-vNopQ/1/index)))"
2 =  "(store(mmapfs(/V/idea/nodes/0/indices/-Puacb8gSQG4UAvr-vNopQ/2/index)))"
3 =  "(store(mmapfs(/V/idea/nodes/0/indices/-Puacb8gSQG4UAvr-vNopQ/3/index)))"
4 = "(store(mmapfs(/V/idea/nodes/0/indices/-Puacb8gSQG4UAvr-vNopQ/4/index)))"
 

target 值为:

1
2
3
 
store(mmapfs(/Volumes/RamDisk/idea/nodes/0/indices/Dcfi3m9kTW2Dfc2zUjMOoQ/0/index))

Elasticsearch 调优之 shrink的更多相关文章

  1. Elasticsearch 调优 (官方文档How To)

    How To Elasticsearch默认是提供了一个非常简单的即开即用体验.用户无需修改什么配置就可以直接使用全文检索.结果高亮.聚合.索引功能. 但是想在项目中使用高性能的Elasticsear ...

  2. 别再说你不会 ElasticSearch 调优了,都给你整理好了

    来源:http://tinyurl.com/y4gnzbje 第一部分:调优索引速度 第二部分-调优搜索速度 第三部分:通用的一些建议 英文原文:https://www.elastic.co/guid ...

  3. ElasticSearch 调优

    来源:http://tinyurl.com/y4gnzbje 第一部分:调优索引速度 第二部分-调优搜索速度 英文原文:https://www.elastic.co/guide/en/elastics ...

  4. 别再说你不会ElasticSearch调优了,都给你整理好了

    ES 发布时带有的默认值,可为 ES 的开箱即用带来很好的体验.全文搜索.高亮.聚合.索引文档 等功能无需用户修改即可使用,当你更清楚的知道你想如何使用 ES 后,你可以作很多的优化以提高你的用例的性 ...

  5. ElasticSearch调优问题

    1. 近期遇到一个ES内存居高不下的问题,查了查,发现ES有个fielddata,当你发起一个查询,分析字符串的聚合将会被加载到 fielddata,如果这些字符串之前没有被加载过.如果结果中 fie ...

  6. Elasticsearch 调优之 写入速度优化到极限

      基于版本: 2.x – 5.x 在 es 的默认设置,是综合考虑数据可靠性,搜索实时性,写入速度等因素的,当你离开默认设置,追求极致的写入速度时,很多是以牺牲可靠性和搜索实时性为代价的.有时候,业 ...

  7. Elasticsearch调优篇-慢查询分析笔记

    前言 elasticsearch提供了非常灵活的搜索条件给我们使用,在使用复杂表达式的同时,如果使用不当,可能也会为我们带来了潜在的风险,因为影响查询性能的因素很多很多,这篇笔记主要记录一下慢查询可能 ...

  8. Elasticsearch 调优之 搜索速度优化

    本章讨论搜索速度优化:搜索速度与系统资源.数据索引方式.查询方式等多方面 1.为文件系统cache预留足够的内存 1)应用程序一般情况下,读写都会被操作系统“cache” 2)cache保存在物理内存 ...

  9. PB级大规模Elasticsearch集群运维与调优实践

    导语 | 腾讯云Elasticsearch 被广泛应用于日志实时分析.结构化数据分析.全文检索等场景中,本文将以情景植入的方式,向大家介绍与腾讯云客户合作过程中遇到的各种典型问题,以及相应的解决思路与 ...

随机推荐

  1. dedecms5.7怎么安装百度编辑器

    用过dedecms的朋友都知道dede自带的文本编辑器很不好用,且有些功能还需要我们自己手动去修改源码,才能完成我们想要的效果.现在广大用dedecms的朋友们,你们有福啦!我们可以利用百度的Uedi ...

  2. 正整数序列 Help the needed for Dexter ,UVa 11384

    题目描述 Description 给定正整数n,你的任务是用最少的操作次数把序列1, 2, …, n中的所有数都变成0.每次操作可从序列中选择一个或多个整数,同时减去一个相同的正整数.比如,1,2,3 ...

  3. 稀疏检出-使用git检索出仓库里的某一个目录文件,而不是整个仓库的所有文件

    具体工作意义是从某一个Git仓库 克隆时,只克隆检测出这个仓库里的某些文件夹内容,而不是跟平常那样把整个仓库的内容都克隆下来 从1.7.0版本开始git提供稀疏检出的功能.所谓稀疏检出就是本地版本库检 ...

  4. Ubuntu下添加定时任务执行php文件

    //添加自动下载定时任务1. vim /etc/crontab2. 添加 #每5分钟执行一次*/5 * * * * root /usr/bin/php /home/wwwroot/123.php3. ...

  5. eclipse 部署Tomcat 只有web-inf webapps没有项目文件

    只有webapps 修改eclipse 默认的 发布位置改为 tomcat的安装位置 eclipse 默认的web-content 改为webroot ,发布后web-inf目录下才会有webroot ...

  6. Python 2.7.x 和 3.x 版本的重要区别小结

    许多Python初学者都会问:我应该学习哪个版本的Python.对于这个问题,我的回答通常是"先选择一个最适合你的Python教程,教程中使用哪个版本的Python,你就用那个版本.等学得差 ...

  7. [转]全网最!详!细!tarjan算法讲解

    转发地址:https://blog.csdn.net/qq_34374664/article/details/77488976 原版的地址好像挂了..... 看到别人总结的很好,自己就偷个懒吧..以下 ...

  8. nodejs之express的中间件

    express中间件分成三种 内置中间件 static 自定义中间件 第三方中间件 (body-parser) (拦截器) 全局自定义中间件 在请求接口时 有几个接口都要验证传来的内容是否存在或者是否 ...

  9. jQuery笔试题汇总整理

    1 你在公司是怎么用jquery的? 答:在项目中是怎么用的是看看你有没有项目经验(根据自己的实际情况来回答) 你用过的选择器啊,动画啊,表单啊,ajax事件等 配置Jquery环境 下载jquery ...

  10. iOS10推送必看UNNotificationAttachment以及UNTimeIntervalNotificationTrigger

    虽然这篇文章比较长,也不好理解,但是还是建议大家收藏,以后用到的时候,可以看看,有耐心的还是读一读. 这篇文章开始,我会跟大家好好讲讲,苹果新发布的iOS10的所有通知类. 一.创建本地通知事例详解: ...