1小时ElasticSearch求生指南

先给出葵花宝典心法口诀:

    节点发现很重要,避免脑裂保平安;出现问题快踢掉,否则查询好不了

    自动恢复要慎重,过于仓促反不好,分片移动成本高,能够避免是最好

    副本开销也挺高,流量大时可去掉,等到夜里静悄悄,定时任务来生成

    拆分索引很靠谱,保留天数按需要,数据采集设拆分,定时删除有脚本

    多节点,是个宝,物理资源利用高,扩容缩容需规范,不能直接(节点)上下线

    写入参数可以调,注意观察看疗效,段合并调整是猛药,慎重避免副作用


一、陷阱的产生

 1.ES的节点类型如下图:

  1. image.png

  2. 默认的配置有问题:

  3. a.ES默认安装后默认的节点类型:Maser-Eligible & Data & Ingest,三合一

  4. b.默认设置里“minimum_master_nodes: 1”,只要看见一个节点,即可成立集群,异常情况下容易发生脑

  5. c.原则:minimum_master_nodes应设置为 (master_eligible_nodes / 2) + 1

 2.Master节点存储信息多

    image.pngimage.png

    为管理ES集群,需要有一些元数据标明集群状态、索引/分片位置、in-sync shards …,这些信息被称为集群的Meta Data。

    集群的Meta data的变更都由Master节点完成,并通知到集群中的其它节点。所以Master稳定对集群很重要。

    默认Master同时作为Data节点,当负载较重时,容易导致稳定性问题

3.高成本的写过程

     image.png

    a. 客户端向Node1 发送写请求

    b.Node1 算出文档属于分片0,于是将写请求转给分片0主分片P0所在的Node3

    c. Node3写成功后,继续将写请求并行转发到Node1和Node2的副本分片上,一旦副本分片报告成功(根据配置不同可选择1个报告成功,多数报告成功,或所有报告成功),

       Node3向协调节点Node1报告成功

    d.Node1向客户端报告成功


  image.png

  一些解释说明:

     a. 写请求到达分片后,先写Lucene文索引,再写Translog

     b.写Lucene索引时,新记录首先被写入缓存,通过定时刷新生成段文件,定时刷新的频率由“refresh_interval”参数控制,默认1s

     c.ES自己控制何时将生成的段文件持久化到磁盘

     d.Translog也是首先写到内存里,并在满足一定条件时flush到磁盘持久化。

       flush到磁盘的时机由两个参数定义:“flush_threshold_size”: “1024mb”;"sync_interval": "60s"


  image.png

    关于段合并:Segments/段太多会给ES带来很大负担,严重影响搜索性能并带来大量文件句柄的消耗,所以ES会自动进行段合并以优化性能。

    但是段合并过程消耗大量I/O和CPU资源,并且ES会对段合并做节流控制,这个过程甚至会引发其它问题

4.高成本的搜索

image.png

  过程描述: 

        a. 默认搜索分为两个阶段,查询阶段与取回阶段

        b. 在查询阶段,客户端将Search请求发送给Node3,Node3将作为本次查询的协调节点。Node3将查询请求转发到每个主分片或副本分片中,如图中的P1和R0,每个主分片或副本分片搜索自身包含的符合查询条件的记录。

        c. 各分片返回自己符合条件,并已排好序的结果给协调节点Node3,由Node3合并各节点返回的结果并过滤出全局符合条件的结果。接下来进入取回阶段。

        d. 在取回阶段,协调节点Node3已在第三步知道全局结果里各记录分别属于哪个分片,并向相应的分片发送取回请求。

        e. 相应分片响应取回请求,并将结果返回给Node3

        f. Node3将合并后的结果返回给客户端,搜索完成

   搜索的开销:

        为保证搜索性能,ES需要将大量段数据保存在内存中,带来相当大的内存开销;同时,排序、聚合等操作也会消耗大量CPU资源。纵观整个搜索过程,可以发现它需要付出高CPU、高I/O的代价。

   查询膨胀问题:

        在查询阶段,会带来搜索膨胀的问题。即协调节点要知道全局结果,必须汇总每个分片的查询结果。

   Example:某索引有30个分片,要查询符合某个条件的第10000笔记录,其过程是什么?

        查询请求发到ES集群中某个节点,该节点充当协调节点并将查询转发到30个分片上

        每个分片返回自己符合结果的前10000笔记录给协调节点,协调节点对总共30w笔记录排序,并确定全局排序结果里第10000笔记录在分片N上

        向该分片N发送get请求,取回该笔记录

        将记录返回给客户端

二、如何被陷入

两大陷阱 -- 稳定性 & 性能

image.png

  1. 稳定性


    a.稳定性陷阱 Example #1:分片丢失,集群变红


    image.png

       问题现象:有分片丢失,集群进入Yellow/Red状态

       普遍程度:非常普遍,我估计你们所有项目均遇见过

       原因 & 解决办法:几乎都是由于节点失联导致分片丢失。节点失联的原因常见是gc,较少见的原因包括“系统问题”和“网络不通”。

       如是gc导致问题,常见应对手段如关闭索引和部署多节点避免gc;如是其它环境因素,通常排除相关 因素后可解决问题

       有用的命令:

          查看未分片的原因:curl -XGET ‘http://<es-ip>:9200/_cat/shards?h=index,shard,prirep,state,unassigned.reason

          查看gc的命令: jstat -gc <es-pid> 2000

    b.稳定性陷阱 Example #2:脑裂无法恢复

        问题现象:某个节点被踢出集群,并再也无法加入进来,集群随后进入分片恢复,当该丢失节点被手动加回集群后,

        普遍程度:较为普遍

        解决办法:合理设置参数,避免集群脑裂

        假设有3个Master Eligible节点:node.master: true

            至少看见2个Master Eligible才可组建集群:discovery.zen.minimum_master_nodes:2

    c.稳定性陷阱 Example #3:再平衡对性能的恶化

        问题现象:发现集群长时间处于黄色状态,大量分片处于分配中或待分配状态,往往伴随着一些节点处于高负载状态的现象。

        普遍程度:普遍

        原因分析:

        当节点由于各种原因失联一段事件后,主节点会:

        1)将失联节点上的每个主分片的一个副本提升为新的主分片;

        2)重新在其它节点上分配副本;

        3)进行分片恢复动作;

        4)如此时失联节点重新加入,主节点将对集群做平衡,将一些分片移动到失联节点上,情况进一步变差

        以上恢复/再平衡过程是CPU、network-io、disk-io都很重的操作!

        如何缓解:合理设置分片恢复延迟,给系统更高的容错度

        “index.unassigned.node_left.delayed_timeout”: “5m“     (默认1分钟)

     d.稳定性陷阱 Example #4:查询响应慢

        问题现象:从ES里加载数据失败

        普遍程度:较为普遍

        原因分析:

        ES集群有数据节点处于异常状态 (如长时间GC),该节点未能被及时踢出集群,导致集群认为该节点仍存活,转发到该节点的查询长时间不能返回,导致页面的查询超时失败。

        在这种情况下,写入数据也会受到影响,如观察采集器状态和日志,很大几率会发现有数据写失败的情况。

        不少项目的ES集群会优化节点的心跳检测参数设置,以降低集群变红的概率和触发自平衡带来的影响,但这种优化在节点异常时,将加重查询响应慢的问题

        如何应对:

        合理规划部署并优化配置,降低节点异常的概率

        非不得已应避免将心跳检测参数设置的过于激进,默认参数在大多数情况下适用,需要调整的情况下也不建议超过下面的值:

        “discovery.zen.ping_interval”: “10s“ 

        “discovery.zen.ping_timeout”: “5s”

        “discovery.zen.ping_retries”: 3

        稳定性陷阱的日志表现


        image.png

    稳定性陷阱的总结:

    表现:ES节点掉出集群,或一段时间没有响应

    诱因

      jvm gc 【常见原因】

      系统问题 【少见】

      网络原因 【极少见】

    危害

      分片丢失,集群变红/黄

      脑裂

      再平衡导致集群性能恶化

      查询响应时间很长/超时


 2.性能陷阱:短板效应很明显

  a.性能陷阱 Example #1:I/O慢导致集群性能差

    问题现象:集群表现不稳定,采集器大量丢日志;查看ES日志经常出现长时间gc (> 30秒);在监控页面中观察会发现多数节点CPU、load经常飙红,CPU使用率超过硬件能力的70%

    普遍程度:较少见

    原因分析:ES为提高性能,做了很多优化,包括通过轮询操作替代睡眠、等待通知等阻塞操作(特别是段合并的节流控制处理逻辑)。

    当磁盘写速度跟不上时,段合并逻辑会不断重试合并,直到可以写入,表现为检测到磁盘I/O写入不高,但CPU,load非常高。

    如何解决:

        有条件采用RAID5 (非常有效,推荐)

        使用高性能磁盘 (有效)

    没有RAID5的情况下,部署多节点,给不同节点分片的data目录分配不同的磁盘以隔离I/O    (一般) 

    补充:评判硬盘性能是否满足数据量要求的条件不等式 (仅用于评估IO能否满足)

    (eps × 每条日志大小 × (1 + 副本数) × 2[1] × 1.5[2]) ÷ data节点数 < 磁盘写速度 × 0.4[3]

    其中[1]为ES写段和写Translog的影响因子;[2]为段合并的影响因子;

    3]为考虑两重影响因素的调整因子:

       1)ES data节点由于段合并有大量读操作,影响写入性能;

       2)ES的段落磁盘时不是顺序写文件 (均为经验参数,可根据实际情况调整)

      Example: 1w eps,日志平均1.5KB/条,1份副本,2个data节点,机器配置速度为180MB的硬盘,能否满足性能要求?

  答:不等式左边:10000 * 1.5K * 2 * 2 * 1.5 ÷ 2 ≈ 45MB;不等式右边:180 * 0.4 =72MB。可以满足

b.性能陷阱 Example #2:节点慢导致集群性能差

    问题现象:采集器丢日志,但通过监控页面观察,ES节点大多数时间正常,消耗资源较低,但长时间观察,能看到CPU,load飙红的情况,持续一段时间后消失,过段时间再出现,… …

    普遍程度:较少见

    原因分析:当ES集群中存在配置较低,或速度较慢的节点时,该节点将拉慢其它正常节点的写速度,并触发段合并的节流机制,导致CPU、load飙升;

                     事实上,查询也会受到影响,会表现出有时查询慢的现象。

    如何解决:找出存在瓶颈的节点,并予以解决。

    问题排查的有效命令:

        curl –XGET “http://es-ip:9200/_cat/thread_pool?v&h=ip,bulk*”

     image.png

  性能陷阱的总结:

    表现:ES集群性能差 -- 丢数据;CPU & load持续高位;采集器报错并陷入异常

    诱因

       磁盘I/O速度慢 【常见原因】

       gc导致节点速度慢 【常见原因】

       低配节点速度慢 【较少见】

    危害

        丢日志

        机器性能用不满、上不去

        CPU & load短时间飙升,集群稳定性变差

三、如何避坑

    避坑的技术:调整部署 & 优化配置

image.png

 1.部署优化之增强稳定性

    节点的设置建议(4个以上数据节点,> 1.5w eps):

    a. 主节点必须由master-only节点承担,Master-only节点配置8G内存

    b. 条件允许则部署单独的coordinate节点负责查询,coordinate节点内存16GB。Coordinate节点配置后,模块里连接ES的配置改为coordinate节点。

    c. 同物理机部署多Data节点,Data节点内存最大31G

        切记给每个节点分配不同的data路径以避免异常情况(如因数据未能加载而造成的分片丢失),特别是在未使用RAID的情况下,让不同的节点的data path在不同硬盘上可以隔离I/O、提升性能

    d. 数据量< 1.5w eps时,物理机<4台,通常不需特殊配置,确保节点发现参数正确。原则:保证超半数master eligible节点被看见才可建立集群。

        原则:保证超半数master eligible节点被看见才可建立集群。

        例如3个Master Eligible节点:node.master:true

        至少看见2个Master Eligible才允许组成集群: discovery.zen.minimum_master_nodes:2

        在节点发现配置里配上所有的Master-Eligible节点:discovery.zen.ping.unicast.hosts: ["x.x.x.x", "x.x.x.y", "x.x.x.z"]

 2.部署优化之增加data节点

    Data节点的配置为:

        conf/elasticsearch.yml:    

        node.master: false    

        node.data: true

    设置好节点发现,将Master-Eligible节点放入配置

        conf/elasticsearch.yml:    

        cluster.name: hansihgt-enterprise    

        node.name: node_N    

        discovery.zen.ping.unicast.hosts: ["x.x.x.x", "x.x.x.y", "x.x.x.z"]

     等待集群自动平衡

  3.部署优化之减少data节点

        将分片迁移到其它节点:

        PUT _cluster/settings{  "transient" : {    "cluster.routing.allocation.exclude._ip" : “x.x.x.x"  }}

        待数据迁移完成,将节点下线

  4.部署优化之增加&减少Master节点

        增加Master节点:

        首先将‘minimum_master_nodes’参考变更到当前的“quorum/过半数“值,如,之前为3个Master-Eligible,现在要增加到4个,则quorum要由2提升到3:

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

        再部署新的Master节点,并在配置文件里设置正确的发现参数

   5.部署优化充分利用硬件资源

        一般采用单台物理机上部署多节点的方式以充分利用内存,以及分散磁盘I/O

        数据节点的内存磁盘比

        给所有ES数据节点启动参数配置的内存之和记为M(注意不是机器的物理内存),每天的索引所占存储记为S,索引打开天数记为N,它们之间的关系应满足:

        M * δ > S * N

        δ为经验参数,取值在96 ~ 128之间 (根据现场经验,该值可以适当激进一些)

        Example:某集群7个数据节点,每个节点配置31GB内存,每天数据量约2.5TB(含副本), δ取100,则最大可打开的索引天数为:

            N < 31 * 7 * 100 ÷ (2.5 * 1024) ≈ 8天

   6.部署优化之合理选择硬件

        磁盘使用:I/O性能对ES性能有很大影响,建议

        有条件应尽量上RAID5

        不能上RAID5尽可能选择高性能硬盘

        网卡选择:数据量大时应使用万兆网卡,

        网络存储:最好都不用!

        迫不得已,唯一的选择:SAN

        由于写入延迟大,不要用NAS

        关于虚拟机:最好不用虚拟机 ,迫不得已,应尽量保证硬件资源不被其它虚拟机竞争

    7.优化配置之使用方法优化

        流量高峰时不写副本,设置定时任务生成

       拆分索引,便于不同业务数据源的数据保存不同的时间周期。

    8.优化配置之ES参数优化

       a. 提升稳定性:

          正确设置节点发现参数,避免脑裂

         延迟迁移分片:“index.unassigned.node_left.delayed_timeout”: “5m“

       b.优化写性能 : 

        降低段刷新频率:"index.refresh_interval": "60s“

       c.降低IO阻塞:

            "index.merge.scheduler.max_thread_count": "1“

             action.wait_for_active_shards: 1  (ES 5.x以后)

             action.write_consistency: one (ES 2.x)

       d.段合并参数配置,减少段合并(慎重,有副作用!)

          "index.merge.scheduler.max_merge_count": 16

           "index.merge.policy.floor_segment": "128mb"

           "index.merge.policy.segments_per_tier": 128

           "index.merge.policy.max_merge_at_once”: 32


哈哈:方法千万条,稳定第一条,规划不完善,上线满头汗!

猜你喜欢

转载自blog.51cto.com/14743302/2482588