前言|
本文将介绍几个ES集群生产运维中用得比较多的API,方便大家操作维护日常的运维问题。
一、Split API 介绍
Split 能将一个索引中的大分片切割成若干小的分片,如果一个索引特别大,主分片又比较少,我们可以使用它来进行相关的操作。执行Split API 有以下前置条件:
二、Split API 实践
Split API 在ES6环境下与ES7还有所不同,在ES6环境下,源索引在创建的时候必须要指定 "index.number_of_routing_shards“参数,如果存量索引没有预先配置这个参数,在ES6环境下是无法执行此Split操作的。下面我们将分别实践测试:
- 环境: ES 7.5.1
第一步: 源索引停写:
代码语言:javascript复制PUT logstash-cms5885_001/_settings //假设索引主分片数量为1
{
"settings":{
"index.blocks.write": true
}
}
第二步:执行split 操作:
代码语言:javascript复制
POST logstash-cms5885_001/_split/logstash-cms5885_001_new //目标索引必须不存在
{
"settings":{
"index.number_of_shards": 10 //必须是源索引分片数的倍数,切成10个
}
}
第三步:取消目标索引只读,恢复写功能
代码语言:javascript复制PUT logstash-cms5885_001_new/_settings
{
"settings":{
"index.blocks.write": false
}
}
最后:用户确认新索引无误后删除源索引以释放空间。
- 环境 ES 6.8.2
刚前面的文章说了,如果是ES6的环境,源索引必须具备“the number of routing shards”属性,
如果不具备这个参数,在执行上面的API时,报错如下,API无法执行。
因此,ES6环境下正常的split操作流程应该是这样:
代码语言:javascript复制PUT testserver{
"settings": {
"index.number_of_shards" : 3, //主分片数
"index.number_of_replicas": 0,
"index.number_of_routing_shards" : 30 //将来可以支持切割的主分片数的最大数,这个值应该设置的足够大,建议设置为主分片数的倍数
}
}
接下来,设置只读属性,
代码语言:javascript复制PUT /testserver/_settings
{
"settings": {
"index.blocks.write": true
}
}
接下来,我们进行切割:
代码语言:javascript复制POST testserver/_split/testserver-target?copy_settings=true
{
"settings": {
"index.number_of_shards": 5
}
}
报错如下:
代码语言:javascript复制{
"error": {
"root_cause": [
{
"type": "remote_transport_exception",
"reason": "[1609341716000179332][10.1.3.9:9300][indices:admin/resize]"
}
],
"type": "illegal_argument_exception",
"reason": "the number of source shards [3] must be a factor of [5]" //目标主分片数不是源的倍数
},
"status": 400
}
OK,那我们换成6试试,执行成功。
代码语言:javascript复制POST testserver/_split/testserver-target?copy_settings=true
{
"settings": {
"index.number_of_shards": 6,
"index.number_of_replicas":0
}
}
//
{
"acknowledged" : true,
"shards_acknowledged" : true,
"index" : "testserver-target"
}
我们可以使用GET _cat/shards/testserver-target,查看目标索引的分片分布
如果目标索引的个数大于30呢,我们看看是什么效果?很明显,是不可以的。路由分片的个数必须是目标索引主分片数的倍数。
代码语言:javascript复制POST testserver/_split/testserver-target?copy_settings=true
{
"settings": {
"index.number_of_shards": 36,
"index.number_of_replicas":0
}
}
反馈如下:
{
"error": {
"root_cause": [
{
"type": "remote_transport_exception",
"reason": "[1609341716000179332][10.1.3.9:9300][indices:admin/resize]"
}
],
"type": "illegal_state_exception",
"reason": "the number of routing shards [30] must be a multiple of the target shards [36]"
},
"status": 500
}
因此,我们基于上面的测试可以知道,在ES6环境下,目标索引主分片数必须是源索引分片数的倍数,必须大于源分片数,同时必须小于路由分片数。
那么,在ES6环境下,对于那些集群存量的数量大同时分片比较少的索引,在不适合使用split的环境下,我们还能用什么方法去切割索引呢,可以使用Reindex来操作。
三、Reindex 介绍、实践
reindex是数据复制的API ,实际生产中用的比较多,这里重点讲解一下其实际如何操作。
第一步:先创建目标索引,指定mapping、settings分片数
代码语言:javascript复制PUT 目标索引
{
"settings": {
"index.number_of_shards" : 20,
"index.number_of_replicas": 0,
"index.number_of_routing_shards" : 60,
"index.mapping.total_fields.limit": 2000
}
}
第二步:执行如下API:
代码语言:javascript复制
如果索引比较大,可以加一个参数,放到后台执行
POST _reindex?wait_for_completion=false
{
"source": {
"index": "index_A"
},
"dest": {
"index": "index_目标索引"
}
}
第三步: 执行上面的API,会生成一个TaskID ,
代码语言:javascript复制{
"task" : "xWyhGhgpSqGGJA9CtWciaQ:2244774"
}
d
第四步: 查看复制进度,通过GET _tasks/taskID的方式进行查看
代码语言:javascript复制GET _tasks/xWyhGhgpSqGGJA9CtWciaQ:2244774
Response,如下
四、 Shrink API
Shrink API 的作用:可以将索引的主分片数收缩到较小的值。会使用和源索引相同的配置去创建索引,仅仅降低主分片数。
因为Shrink API 采用硬链接的方式去读取文件,因此它的性能比reindex会好很多,但是它也有很多的限制
- 源分片数必须是目标分片数的倍数,如果源分片数是素数,目标分片数必须是1;
- 文件系统支持硬链接,会将segments硬链接到目标索引,所以性能好;
- 在执行shrink API的时候,会执行一系列的验证,如下信息
- 分片必须只读
- 所有的分片必须在同一节点上
- 集群健康状态为green
五、 Shrink API 实践
第一步,先创建一个源索引
代码语言:javascript复制PUT my_source_index
{
"settings": {
"number_of_replicas": 0,
"number_of_shards": 3
}
}
第二步,尝试写入一个文档
代码语言:javascript复制PUT my_source_index/_doc/1
{
"key":"value"
}
第三步,查看该索引分片分布 GET /_cat/shards/my_source_index
第四步, 执行如下API,将分片减少到2个,看能否成功。
代码语言:javascript复制POST my_source_index/_shrink/my_target_index
{
"settings": {
"index.number_of_replicas": 0,
"index.number_of_shards": 2,
"index.codec": "best_compression"
},
"aliases": {
"my_search_indices": {}
}
}
报错如下:
大概意思是:源分片数要能整除目标分片数,是其的倍数。那我们调整成1,再试试
代码语言:javascript复制POST my_source_index/_shrink/my_target_index
{
"settings": {
"index.number_of_replicas": 0,
"index.number_of_shards": 1,
"index.codec": "best_compression"
},
"aliases": {
"my_search_indices": {}
}
}
上面的报错消失,又有新错。如下:
源索引要设置成,只读,执行如下命令
代码语言:javascript复制 PUT my_source_index/_settings
{
"settings":{
"index.blocks.write":true
}
}
再次执行shrink操作
代码语言:javascript复制POST my_source_index/_shrink/my_target_index
{
"settings": {
"index.number_of_replicas": 0,
"index.number_of_shards": 1,
"index.codec": "best_compression"
},
"aliases": {
"my_search_indices": {}
}
}
报错如下:
意思是,所有的源索引的所有分片必须是在同一节点上。可以使用如下API调整分片所属节点信息
代码语言:javascript复制PUT my_source_index/_settings
{
"index.routing.allocation.require._ip": "172.16.15.6"
}
再次查看源索引的分片节点信息是否在同一节点上,如下:
再次执行如下命令,执行Shink操作
代码语言:javascript复制POST my_source_index/_shrink/my_target_index
{
"settings": {
"index.number_of_replicas": 0,
"index.number_of_shards": 1,
"index.codec": "best_compression"
},
"aliases": {
"my_search_indices": {}
}
}
返回成功
查看目标索引的分片信息,如下截图:
再次查看目标索引的文档内容是否正常,如下,返回正常。
这样,Shrink API操作成功。过程还是有点点复杂。
六、总结
今天花点时间动手总结了几个常用的API,希望能帮到大家,后续将更新更多的使用的操作API。