搜索引擎 升级 Elasticsearch 集群数量实战记录

pathbox · July 31, 2017 · 9311 hits

现在线上有一个 elasticsearch 集群搜索服务有三台 elasticsearch 实例(es1、es2、es3),打算将其升级为 5 台(增加 es4、es5)。这篇文章主要是对整个操作的过程记录,以及出现的问题总结,包括移动数据量所需要的时间。因为,一开始由于不知道线上数据量全部分配完需要多少时间,如果从凌晨开始操作,到早上 8 点都还没有同步完,这样会影响到白天线上业务的正常使用。

准备阶段

线上 es 集群使用的是阿里云服务器,copy 其中一个镜像。然后更改其 elasticsearch.yml 配置文件,检查 IK 插件是否安装成功。按照这个流程,准备两台新的服务器放入阿里云的隔离组,并安装好 elasticsearch,测试 elasticsearch 实例可以正确启动。也做了将这两台服务器构建一个集群的测试。开始升级操作前 30 分钟,再次检查 elasticsearch.yml 配置。主要的修改是:

discovery.zen.minimum_master_nodes:3
discovery.zen.ping.unicast.hosts: ["es1_ip", "es2_ip","es3_ip","es4_ip","es5_ip"]

升级操作

关闭 es 集群 shard 分配功能。对 es1 执行:

curl -XPUT es1_ip:9200/_cluster/settings -d '{
  "transient": {
   "cluster.routing.allocation.enable": "none"
   }
}'

然后检查:

curl es1_ip:9200/_cluster/settings
curl es2_ip:9200/_cluster/settings
curl es3_ip:9200/_cluster/settings

得到的结果是:

{"transient":{"cluster":{"routing":{"allocation":{"enable":"none"}}}}}

说明 es 集群已经关闭 shard 分配功能

关闭 es1、es2、es3 上的 monit

sudo service monit stop

手动控制 elasticsearch 进程的启动,避免 monit 自动拉起 elasticsearch 进程导致意外问题

这时,新的两台服务器 es4、es5 还在隔离组。把隔离取消,然后启动这两台服务器的 elasticsearch 实例

使用目录下面写好的启动脚本,这个脚本可以在启动时,为 elasticsearch 获取所设定的内存 (控制分配给 es 进程的最大内存、最小内存),JVM 的设置等

./elasticsearch.sh start

执行

curl es1_ip:9200/_cat/nodes
curl es1_ip:9200/_cat/shards
curl es1_ip:9200/_cat/health
curl es1_ip:9200/_cat/indices

验证 nodes 节点信息是否变为五个,以及 shard 现在的分布情况,应该只分布在 es1、es2、es3 上。es4 和 es5 还没有 shard

然后记录下当前的 indices 信息

例子:

health status index    pri rep docs.count docs.deleted store.size pri.store.size
green  open   users     5   1   15036978      4262221     13.2gb          6.6gb
green  open   posts     5   1   15036978      4262221     13.2gb          6.6gb

我们可以看到索引的健康度、状态、文档数量、数据大小和主分片数量、副分片的倍数设置。记录下这些信息,在最后升级完的时候 进行比对,看是否有偏差。如果一切正常,这些信息是不会变的。

启动 es 集群 shard 分配功能

这是集群操作,所以只要对其中一台 es 实例操作即可

curl -XPUT es1_ip:9200/_cluster/settings -d '{
  "transient": {
   "cluster.routing.allocation.enable": "all"
   }
}'

shard 分配开始

执行:

curl es1_ip:9200/_cat/shards

curl es1_ip:9200/_cat/health

curl es1_ip:9200/_cat/indices

curl es1_ip:9200/_cat/recovery
  • 观察 shards 分布情况,是否向 es4 和 es5 分配 shards。以及分配的百分比进度
  • 监控 es4 和 es5 服务器的 elasticsearch 的 log
  • 登入 es4 和 es5,查看挂载的 SSD 数据盘数据量是否在增长
  • 测试进行 es 搜索的测试,快速搜索,工单筛选,客户筛选,观察对线上业务的影响

这段时间,主要使用:

curl es1_ip:9200/_cat/shards

curl es1_ip:9200/_cat/health

curl es1_ip:9200/_cat/recovery

观测 shard 分配进度和情况,以及线上系统健康度。

curl es1_ip:9200/_cat/shards 可以看见具体哪个索引的,哪个 es 服务器在移动 shard 到另一台 es 服务器

正在shard移动时的状态
posts r RELOCATING  3628884   5.4gb es_ip1   elasticsearch1 -> es_ip5 elasticsearch5

可以看到哪个索引,哪个 shard 分片,从哪台服务器上移到另一台服务器上

这个过程发现,elasticsearch 会选择将 reproduction shard(副本分片) 移到新的 elasticsearch 服务器上,而避免移到主分片。

这样可以避免移到主分片时候发生数据丢失的情况,而移动副本分配不用担心这个问题,并且线上的 health 一直是 green。尽可能不影响线上正常搜索业务。

移动 shard 默认是两个并发操作。一开始误解了,以为每个 es 实例会进行两个并发的 shard 移动,会有 6 个 shard 在并发移动,实际情况是,整个集群只有 2 个 shard 在并发移动。下次可以将这个值调大一些,加快 shard 的移动速度,幸好 shard 数据移动的速度比想象的要快。

通过 htop 观察服务器的负载,在进行 shard 分配的服务器,CPU 使用率一般在 20%-40% 之间。服务器是 16 核,也就是一个 elasticsearch 进程 shard 的移动,一个核心都没有跑满,服务器负载在 0.2。可见 elasticsearch 的分片移动还是很保守的,对服务器几乎没有很大的压力。并且观察发现,elasticsearch 不会一次把某个索引该分配的 shard 都分配完再选择下一个索引,而是轮询的分配索引的 shard。A 索引分配了一个 shard,就分配 B 索引的 shard,一圈之后,又回到 A 索引继续分配 shard。直到最后所有索引 shard 数量在集群中平衡。

收尾操作

大约一个小时时间,shard 分配结束。一共将 88G 左右的数据分配到了两台新的服务器上。这是在默认 shard 并发分配数 2 的情况下的时间记录。大家以后可以根据这个记录,预估自己的 elasticsearch shard 分配会需要多少时间。

动态修改 master 选举数量。根据 elasticsearch 文档推荐的公式: (N(master)+1)/2

curl -XPUT es1_ip:9200/_cluster/settings -d '{
      "persistent" : {
          "discovery.zen.minimum_master_nodes" : 3
      }
    }'

检查配置:

{"persistent":{"discovery":{"zen":{"minimum_master_nodes":"3"}}},"transient":{"cluster":{"routing":{"allocation":{"enable":"all"}}}}}

再检测 API 命令

curl es1_ip:9200/_cat/health

curl es1_ip:9200/_cat/indices

curl es1_ip:9200/_cat/shards

这时候,观察到 shard 分配的结果是,每个索引有 10 个 shard,每个 es 服务器拥有一个索引的两个 shard。新加入的 es4、es5 上都是副本 shard,原有集群中的 es1、es2、es3 拥有主 shard 和副本 shard。

例子:

index              shard   prirep   state     docs     store  ip    node
posts               2       r       STARTED   993718   3.5gb es1_ip es1
posts               2       p       STARTED   993718   3.5gb es1_ip es1
posts               0       p       STARTED   993428   3.7gb es2_ip es2
posts               0       p       STARTED   993428   3.7gb es2_ip es2
posts               3       p       STARTED   993653   3.6gb es3_ip es3
posts               3       p       STARTED   993653   3.6gb es3_ip es3
posts               1       r       STARTED   994063   3.5gb es4_ip es4
posts               1       r       STARTED   994063   3.5gb es4_ip es4
posts               4       r       STARTED   993938   3.5gb es5_ip es5
posts               4       r       STARTED   993938   3.5gb es5_ip es5

posts 索引的十个 shard 分片在每台 elasticsearch 服务器上有两个分片。perfect!(实际结果是乱序的)

后悔的操作选择

我们修改了 es1 的配置文件,想要重启 es1 elasticsearch 实例。重启后,发生了意想不到的事情,索引的 shard 又开始分配移动,等了快 40 分钟分配移动结束,但是,这时候不是每个 es 服务器平均拥有一个索引的两个 shard,而是有的 es 服务器有该索引的三个 shard。

posts               2 r STARTED   993718   3.5gb es4_ip es4
posts               2 p STARTED   993718   3.5gb es2_ip es2
posts               0 p STARTED   993428   3.7gb es4_ip es4
posts               0 r STARTED   993428   3.7gb es1_ip es1
posts               3 r STARTED   993653   3.6gb es1_ip es1
posts               3 p STARTED   993653   3.6gb es2_ip es2
posts               1 r STARTED   994063   3.5gb es5_ip es5
posts               1 p STARTED   994063   3.5gb es1_ip es1
posts               4 r STARTED   993938   3.5gb es5_ip es5
posts               4 p STARTED   993938   3.5gb es3_ip es3

posts 在 elasticsearch1 上出现了三个 shard

实际上,原本集群中的三台服务器是不用重启的,你可以修改他们 elasticsearch.yml 配置中的单拨数组设置:discovery.zen.ping.unicast.hosts。加上新加的两台服务器的 ip,和 discovery.zen.minimum_master_nodes:3。下次重启的时候,就会读取这个新的配置,而不需要马上重新。因为,k 可以通过调用 API 的方式,动态配置 discovery.zen.minimum_master_nodes,而 discovery.zen.ping.unicast.hosts 的配置,在新的 elasticsearch 服务器上配置五台服务器的 ip 地址就可以了。

打开所有 es 服务器的 monit,测试线上 elasticsearch 搜索功能

修改项目代码,加上新加的两台 elasticsearch 服务器 IP

No Reply at the moment.
You need to Sign in before reply, if you don't have an account, please Sign up first.