Elasticsearch Allocation Module 底层原理及参数优化深入剖析-搜索系统线上实战

1,343 阅读7分钟

本套技术专栏作者(秦凯新)专注于大数据及容器云核心技术解密,具备5年工业级IOT大数据云平台建设经验,可提供全栈的大数据+云原生平台咨询方案,请持续关注本套博客。QQ邮箱地址:1120746959@qq.com,如有任何学术交流,可随时联系。

1. disk-based shard allocation 参数优化

  • es在进行shard allocation的时候,会充分考虑每一个node的可用磁盘空间。
  • cluster.routing.allocation.disk.threshold_enabled:默认是true,如果是false会禁用基于disk的考虑
  • cluster.routing.allocation.disk.watermark.low:控制磁盘使用率的低水位,默认是85%,如果一个节点的磁盘空间使用率已经超过了85%,那么就不会分配shard给这个node了
  • cluster.routing.allocation.disk.watermark.high:控制磁盘使用率的高水位,默认是90%,如果一个节点的磁盘空间使用率已经超过90%了,那么就会将这个node上的部分shard移动走
  • cluster.info.update.interval:es检查集群中每个node的磁盘使用率的时间间隔,默认是30s
  • cluster.routing.allocation.disk.include_relocations:默认是true,意味着es在计算一个node的磁盘使用率的时候,会考虑正在分配给这个node的shard。

2. shard allocation awareness参数优化

2.1 基本配置

  • 如果在一个物理机上运行多个虚拟机,并且在多个虚拟机中运行了多个es节点,或者在多个机架上,多个机房,都有可能有多个es节点在相同的物理机上,或者在相同的机架上,或者在相同的机房里,那么这些节点就可能会因为物理机,机架,机房的问题,一起崩溃。
  • 如果es可以感知到硬件的物理布局,就可以确保说,priamry shard和replica shard一定是分配到不同的物理机,或者物理机架,或者不同的机房,这样可以最小化物理机,机架,机房崩溃的风险
  • shard allocation awareness可以告诉es我们的硬件架构,
    ./bin/elasticsearch -Enode.attr.rack_id=rack_one,也可以在elasticsearch.yml中设置这个机架id
    cluster.routing.allocation.awareness.attributes: rack_id
    node.attr.rack_id=rack_one
  • 上面的两行设置里,第一行是设置机架id的属性名称,第二行是用那个机架id属性名称设置具体的机架id。如果启动两个node,都在一个机架上,此时创建一个有5个primary shard和5个replica shard的索引,此时shards会被分配到两个节点上。
  • 如果再启动两个node,设置为另外一个机架,此时es会将shard移动到新的node上,去确保说,不会让primary shard和其replica shard在同一个机架上。但是如果机架2故障了,为了恢复集群,那么还是会在恢复的时候,将shards全部在机架1上分配的
  • prefer local shard机制:在执行search或者get请求的时候,如果启用了shard awareness特性,那么es会尽量使用local shard来执行请求,也就是在同一个awareness group中的shard来执行请求,也就是说尽量用一个机架或者一个机房中的shard来执行请求,而不要跨机架或者跨机房来执行请求
    可以指定多个awareness属性,比如机架id和机房名称,类似下面:
    cluster.routing.allocation.awareness.attributes: rack_id,zone

2.2 强制性的感知

  • 如果现在我们有两个机房,并且有足够的硬件资源来容纳所有的shard,但是可能每个机房的硬件只能容纳一半shard,不能容纳所有的shard。如果仅仅使用原始的感知特性,如果一个机房故障了,那么es会将需要恢复的shard全部分配给剩下的一个机房,但是剩下的那个机房的硬件资源并不足以容纳所有的shard。
  • 强制感知特性会解决这个问题,因为这个特性会绝对不允许在一个机房内分配所有的shard
    比如说,有一个感知属性叫做zone,有两个机房,zone1和zone2,看看下面的配置:
    cluster.routing.allocation.awareness.attributes: zone
    cluster.routing.allocation.awareness.force.zone.values: zone1,zone2 
    那么此时如果将2个node分配给zone1机房,然后创建一个索引,5个primary shard和5个replica shard,
    但是此时只会在zone1机房分配5个primary shard,只有我们启动一批node在zone2机房,才会分配replica shard

2.4 shard allocation filtering

  • shard allocation filtering可以让我们允许或者不允许某些index的shard分配给一些特殊的节点,典型的用途,就是如果我们要下线一些node,就可以用这个feature禁止shard分配给这些即将下线的node,而且我们还可以将这些即将下线的节点的shard移动到其他节点。
  • 用下面的命令可以下线一个节点,因为就不允许将shard分配给这个节点了
    PUT _cluster/settings
    {
      "transient" : {
        "cluster.routing.allocation.exclude._ip" : "10.0.0.1"
      }
    }

2.5 node下线时的shard延迟分配

  • 如果从集群中下线一个节点,master会做下面这些事情,这些操作可以保护集群不会丢失数据,因为会对每个shard都复制充足的replica shard
    (1)如果那个节点上有primary shard,那么master会将那些primary shard在其他节点上的replica shard提升为primary shard
    (2)分配新的replica shard来保证replica数量充足
    (3)在剩下的各个node上进行shard rebalance,确保负载均衡
  • 但是这个过程,可能会导致集群中出现很重的负载,包括网络负载和磁盘IO负载,如果那个下线的节点只是因为故障被下线,马上就会有新的节点来顶替它,那么这种立即执行的shard recovery过程是不需要的,考虑下面的场景:
    (1)某个node跟集群丢失了网络连接
    (2)master node将那个node上的primary shard对应的其他节点上的replica shard提升为primary shard
    (3)master node分配新的replica shard到其他节点上
    (4)每个新的replica shard都会通过网络传输一份primary shard的完整的副本数据
    (5)很多shard都被移动到其他的node来让集群rebalance
    (6)但是几分钟以后,那个丢失了网络连接的node又重新连接到了集群中
    (7)master节点又要再次进行rebalance操作,因为需要将一些shard分配给那个node
  • 其实如果master node也许只要等待几分钟,那么丢失的那个node自己会回来,丢失的shard也会自动恢复过来,因为数据都在节点的本地,不需要重新拷贝数据以及网络传输,这个过程是非常快速的
  • index.unassigned.node_left.delayed_timeout,这个参数可以设置某个节点下线之后, 对应的replica shard被重新复制和分配的时间等待期,默认是1m,可以通过下面的命令来修改:
    PUT _all/_settings
    {
      "settings": {
        "index.unassigned.node_left.delayed_timeout": "5m"
      }
    }
  • 如果启用了delayed allocation之后,那么就会看到下面的场景:
    (1)某个node丢失了网络连接
    (2)master将那个node上的一些primary shard对应的其他node上的replica shard提升为primary shard
    (3)master记录下来一条消息日志,这个primary shard的replica shard还没有重新分配和开始,被delayed了,会等待1m
    (4)cluster会保持yellow状态,因为没有足够的replica shard
    (5)那个丢失了的node在几分钟之后,如果回到了集群中
    (6)缺失的那些replica shard会直接分配给那个node,使用其本地的数据即可
  • 如果某个node确定了肯定不会再回到集群中,那么可以通过下面的命令,手动设置一下,直接不等待那个节点回来了
    PUT _all/_settings
    {
      "settings": {
        "index.unassigned.node_left.delayed_timeout": "0"
      }
    }

2.6 索引恢复的优先级

  • 没有被分配的shard都是按照优先级来分配的,有下面几个优先级,index.priority,索引的创建日期,索引名称
    PUT index_3
    {
      "settings": {
        "index.priority": 10
    }

2.7 每个节点的shard数量

cluster.routing.allocation.total_shards_per_node,设置每个节点最多承载的shard数量,默认是无限制的

3 总结

生产部署还有很多工作要做,本文从初级思路切入,进行了问题的整合。

本套技术专栏作者(秦凯新)专注于大数据及容器云核心技术解密,具备5年工业级IOT大数据云平台建设经验,可提供全栈的大数据+云原生平台咨询方案,请持续关注本套博客。QQ邮箱地址:1120746959@qq.com,如有任何学术交流,可随时联系

秦凯新

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。