ElasticSearch2.2.1集群迁移发生的问题

8 篇文章 0 订阅

背景

公司内网测试环境的es集群,机器性能极差,每个节点只能分配2个G的内存,并且磁盘还用的网络磁盘。es的操作权限通过dubbo接口来完成,然而由于es的性能比较差,每个操作执行的时间较长,应用接口大量的调用,dubbo超时后重试,导致很快dubbo线程池写满,一个应用大量的写入后就导致了其他应用的不可用。且由于dubbo的版本低,没有有效的限制控流手段无法踢出大量调用的应用,这样导致整个接口的消费者都不可用。因此决定把es集群迁移到两台物理机上面。

准备

拷贝正在运行的elastic包,复制到要新启动的机器上面。为什么不用新安装包呢?因为里面有配置信息,所以想改吧改吧就可以使用,不想造成配置信息不同步的情况。在修改的时候注意如果是同一网段,保证cluster-name一致即可加入集群。不同网段需要配置一个集群现有的节点,以便可以接引过去。discovery.zen.ping.unicast.hosts: [“1.2.3.4”] (在这里配置一个老集群的节点即可)。cluster.name;node.name;network.host;path.data;同时修改这几个配置。data,log 路径建议放在elastic安装包的外部,这样安装包除了配置以外就是一个干净的包,不会被数据污染。修改 elasticsearch.in.sh 下内存的大小,es有个配置可以锁定内存(即暂时用不到,也把内存先抢过来不分配给其他应用)

启动

es的启动会检查很多信息。例如是否是es用户启动,文件打开句柄数,等。具体安装过程中的问题可以参考我另一篇文章
ElasticSearch6集群搭建及踩坑 里面有一些安装启动过程中发现的问题,基本可以解决大部分人遇到的情况。

问题

启动不起来

由于配置没有修改干净发生冲突(因为是复制过来的嘛),配置格式不正确等,此等问题检查配置文件即可。

加入不了集群

不在一个网段,cluster.name 不一致,node.name冲突 等,修改错误的配置即可。

主分片丢失

由于主分片只有一份,没有设置副本,新机器加入后,剔除老机器的时候,主分片在老机器上面,集群无法恢复,就会显示Red状态。解决:再次启动一下节点,利用 curator 这个es运维工具,把分片移动到其他机器上,待该机上面没有主分片后shutdown即可。

副本不恢复

按照以上步骤,逐渐剔除老机器后发现,有些索引的主分片迁移成功,但是副本却不会迁移过来。无论怎么刷新索引都不成功。

处理方式一

检查缺少副本的索引名称

curl -XGET -s https://ip:port/_cat/shards | grep UNASSIGNED
eslog1                 3 p UNASSIGNED
eslog1                 3 r UNASSIGNED
eslog1                 1 p UNASSIGNED
eslog1                 1 r UNASSIGNED
索引名称				索引编号 主/副 状态

分配分片

curl -XPOST 'ip:port/_cluster/reroute' -d '{
    "commands" : [ {
          "allocate" : {
              "index" : "eslog1",		##索引名称
              "shard" : 4,				##分片编号
              "node" : "es1",			##要迁移到的节点
              "allow_primary" : true	
          }
        }
    ]
}'

分配时可能遇到的坑,需要注意的地方
分配时带参数"allow_primary" : true
allocate 在某些版本是 allocate_replica
然而以上的方案并不能解决我的问题

处理方式二

思考可能性:是不是有些副本文件有问题,导致无法分配呢?
那么我删除副本,在重新分配是不是可以了呢?

  1. 把待分配的索引的副本设置为0
curl -XPUT -s https://ip:port/{index-name}/_settings                -d '{"number_of_replicas":"0"}'
  1. 待集群green后,再设置为1
curl -XPUT -s https://ip:port/{index-name}/_settings                -d '{"number_of_replicas":"1"}'

然而还是不能解决问题

处理方式三

由于集群设置了 分片分布规则设置 导致了分片主副本不能再同一个机房,去掉这个配置,使用方式二同步即可

cluster.routing.allocation.awareness.attributes: rack_id,zone

附带

Eleastisearch6.2.2 索引的时候报了一个错误:

ClusterBlockException[blocked by: [FORBIDDEN/12/index read-only / allow delete (api)];]
按照 Eleastisearch 官方文档给的解决办法是

An example of resetting the read-only index block on the twitter index:

PUT /twitter/_settings
{
“index.blocks.read_only_allow_delete”: null
}

按照官方给的这个解决思路,真正在linux 上面执行的时候,请看:

curl -XPUT -H "Content-Type: application/json"
http://127.0.0.1:9200/_all/_settings -d  '{"index.blocks.read_only_allow_delete": null}'

其中 _all 这个可以更改为自己在创建 Eleastisearch 索引的时候的name,用来修改单个索引只读状态,当然用 _all 也可以, _all 是修改了所有的索引只读状态

索引副本未分配的原因

可以通过命令或url查询看到具体的原因:

 curl XGET 'http://ip:9200/_cat/shards?h=index,shard,prirep,state,unassigned.reason' | grep UNASSIGNED

查询结果,最后一列就是原因:

fxcl-2018-12-18                       1 r UNASSIGNED NODE_LEFT
f-2018-12-17                          1 r UNASSIGNED NODE_LEFT
fg-2018-12-19                         1 r UNASSIGNED NODE_LEFT

各种原因如下:

1)INDEX_CREATED:由于创建索引的API导致未分配。
2)CLUSTER_RECOVERED :由于完全集群恢复导致未分配。
3)INDEX_REOPENED :由于打开open或关闭close一个索引导致未分配。
4)DANGLING_INDEX_IMPORTED :由于导入dangling索引的结果导致未分配。
5)NEW_INDEX_RESTORED :由于恢复到新索引导致未分配。
6)EXISTING_INDEX_RESTORED :由于恢复到已关闭的索引导致未分配。
7)REPLICA_ADDED:由于显式添加副本分片导致未分配。
8)ALLOCATION_FAILED :由于分片分配失败导致未分配。
9)NODE_LEFT :由于承载该分片的节点离开集群导致未分配。
10)REINITIALIZED :由于当分片从开始移动到初始化时导致未分配(例如,使用影子shadow副本分片)。
11)REROUTE_CANCELLED :作为显式取消重新路由命令的结果取消分配。
12)REALLOCATED_REPLICA :确定更好的副本位置被标定使用,导致现有的副本分配被取消,出现未分配。

elasticsearch高级配置之------分片分布规则设置

分片分布是把索引分片分布到节点的过程。这个操作会在初次启动集群,副本分配,负载均衡,或增加删除节点时进行。

分片分布相关的设置:

cluster.routing.allocation.allow_rebalance
设置根据集群中机器的状态来重新分配分片,可以设置为always, indices_primaries_active和indices_all_active,
默认是设置成indices_all_active来减少集群初始启动时机器之间的交互。

cluster.routing.allocation.cluster_concurrent_rebalance
设置在集群中最大允许同时进行分片分布的个数,默认为2,也就是说整个集群最多有两个分片在
进行重新分布。

cluster.routing.allocation.node_initial_primaries_recoveries
设置指定初始每个节点。由于多数情况下是使用local的gateway,这应该会更快,

cluster.routing.allocation.node_concurrent_recoveries
设置在节点中最大允许同时进行分片分布的个数,默认为2

cluster.routing.allocation.disable_allocation
使主要分片或副本的分布失效。要知道,如果主分片不存在(那个节点挂了)那么其副本仍然会被提升为主分片,
这个设置只有在动态地使用集群更新设置api调用时才生效。

cluster.routing.allocation.disable_replica_allocation
使副本分布失效。和上一个设置一样,只有动态地使用集群更新设置api调用时才生效。

indices.recovery.concurrent_streams
当从一个点(peer)恢复分片时当前节点最多允许的文件读取流的个数,默认为5

自定义分片分布规则

可以通过设置分片的分布规则来人为地影响分片的分布,下面是个例子:

假设我们有几个机架。当我们启动一个节点,我们可以设置一个叫rack_id(其它名字也可以)的属性,例如下面设置:

node.rack_id: rack_one
上面这个例子设置了一个属性叫rack_id,它的值为rack_one。现在,我们要设置rack_id作为分片分布规则的一个属性(在所有节点都要设置)。

cluster.routing.allocation.awareness.attributes: rack_id
上面设置意味着rack_id会用来作为分片分布的依据。
例如:我们启动两个node.rack_id设置rack_one的节点,然后建立一个5个分片,一个副本的索引。
这个索引就会完全分布在这两个节点上。如果再启动另外两个节点,node.rack_id设置成rack_two,分片会重新分布,
但是一个分片和它的副本不会分配到同样rack_id值的节点上。可以为分片分布规则设置多个属性,例如:

cluster.routing.allocation.awareness.attributes: rack_id,zone
注意:当设置了分片分布属性时,如果集群中的节点没有设置其中任何一个属性,那么分片就不会分布到这个节点中。

强制分布规则

更多的时候,我们不想更多的副本被分布到相同分布规则属性值的一群节点上,那么,我们可以强制分片规则为一个指定的值。

例如,我们有一个分片规则属性叫zone,并且我们知道有两个zone,zone1和zone2.下面是设置:

cluster.routing.allocation.awareness.force.zone.values: zone1,zone2
cluster.routing.allocation.awareness.attributes: zone

现在我们启动两个node.zone设置成zone1的节点,然后创建一个5个分片,一个副本的索引。索引建立完成后只有5个分片(没有副本),只有当我们启动node.zone设置成zone2的节点时,副本才会分配到那节点上。

分片分布过滤

允许通过include/exclude过滤器来控制分片的分布。这些过滤器可以设置在索引级别上或集群级别上。下面是个索引级别上的例子:

假如我们有四个节点,每个节点都有一个叫tag(可以是任何名字)的属性。每个节点都指定一个tag的值。如:节点一设置成node.tag: value1,节点二设置成node.tag: value2,如此类推。我们可以创建一个索引然后只把它分布到tag值为value1和value2的节点中,可以通过设置
index.routing.allocation.include.tag 为value1,value2达到这样的效果,如:

curl -XPUT localhost:9200/test/_settings -d '{   
    "index.routing.allocation.include.tag" : "value1,value2"   
}'  

与此相反,通过设置index.routing.allocation.exclude.tag为value3,我们也可以创建一个索引让其分布在除了tag设置为value3的所有节点中,如:

curl -XPUT localhost:9200/test/_settings -d '{   
    "index.routing.allocation.exclude.tag" : "value3"   
}' 

include或exclude过滤器的值都会使用通配符来匹配,如value*。一个特别的属性名是_ip,它可以用来匹配节点的ip地址。

显然,一个节点可能拥有多个属性值,所有属性的名字和值都在配置文件中配置。如,下面是多个节点的配置:

node.group1: group1_value1
node.group2: group2_value4

同样的方法,include和exclude也可以设置多个值,如:

curl -XPUT localhost:9200/test/_settings -d '{   
    "index.routing.allocation.include.group1" : "xxx"   
    "index.routing.allocation.include.group2" : "yyy",   
    "index.routing.allocation.exclude.group3" : "zzz",   
}' 

上面的设置可以通过索引更新的api实时更新到索引上,允许实时移动索引分片。

集群范围的过滤器也可以定义,可以通过集群更新api实时更新到集群上。这些设置可以用来做让一些节点退出集群的操作。下面是通过ip地址去掉一个节点的操作:

curl -XPUT localhost:9200/_cluster/settings -d '{   
    "transient" : {   
        "cluster.routing.allocation.exclude._ip" : "10.0.0.1"   
    }   
}'  

启动和重启脚本

start.sh


#!/bin/bash

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"

/sbin/runuser - es -s /bin/bash -c "$DIR/start-cmd.sh"

restart.sh

#!/bin/sh
source /etc/profile
cd `dirname $0`
BIN_DIR=`pwd`
cd ..
ES_DIR=`pwd`

PID=`ps -ef|grep ${ES_DIR} |awk '{if($8 ~/java/){ print $2}}' `
if [ ! -z "$PID" ]; then
    kill -9 $PID
fi
sleep 5;
hostname=`hostname`
idc=`echo "$hostname" |awk -F - '{print $1}'`
rack=`echo "$hostname" |awk -F - '{print $2}'`
echo "${BIN_DIR}/elasticsearch -d --node.rack_id=${rack} --node.zone=${idc}"
/sbin/runuser - es -s /bin/bash -c "${BIN_DIR}/elasticsearch -d "
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值