elasticsearch吧 关注:1,519贴子:5,327
  • 10回复贴,共1

8k到13w,记一次elasticsearch写入速度提升的实战案例

只看楼主收藏回复

基本配置
基本配置,5台配置为 24C 125G 17T 的主机,每台主机上搭建了一个elasticsearch节点。 采用的elasticsearch集群版本为7.1.1。管理工具包括kibana和cerebro。


IP属地:四川1楼2019-10-13 10:18回复
    应用案例
    数据来源为kafka的三个topic,主要用于实时日志数据的存储和检索,由于实时性要求,所以需要将数据快速的写入到es中。 这里就分别称它们为TopicA、TopicB、TopicC吧。由于是调优写入,所以对源数据的一些基本的指标需要作出一个详细的梳理,便于后续分析。以下为三个topic的数据产生情况:


    IP属地:四川2楼2019-10-13 12:51
    回复
      规划
      Topic 报文大小 数据量预估(天) es索引分片数规划
      topicA 900b 2T 30个主分片
      topicB 800b 400G 10个主分片
      topicC 750b 300G 10个主分片


      IP属地:四川3楼2019-10-13 12:51
      回复
        问题重现
        未做任何配置的情况下,分别使用java和logstash进行数据抽取,发现效率都不高,具体问题表现在:1、kafka数据积压严重,消费跟不上生产的速度。2、elasticsearch集群负载很高,大量写入被拒绝。3、java程序频繁抛出RejectionException异常。4、主机cpu异常的高。操作系统层面及JVM的配置调整这里不再阐述,有很多关于此类的文章可以参考。我们分模块对各个部分进行调整,具体细节如下:


        IP属地:四川4楼2019-10-13 12:51
        回复
          启动多个进程
          由于Bulkprocess是线程安全的,所以我们可以使用多线程的方式来共享一个批处理器。更好的消费方式是,启动多个消费程序进程,将其部署在不同的主机上,让多个进程中开启的多线程总数和topic的分区数相等,并且将他们设置为同一个消费组。每一个进程包含一个bulkprocess,可以提高消费和批量写入能力。同时可以避免单点问题,假如一个消费者进程挂掉,则kafka集群会重新平衡分区的消费者。少了消费者只是会影响消费速度,并不影响数据的处理。“压测”,提升批量插入条数 通过对各个监控指标的观察,来判断是否能继续提高写入条数或增加线程数,从而达到最大吞吐量。一、观察集群负载Load Average值 负载值,一定程度上代表了CPU的繁忙程度,那我们如何来解读elasticsearch 监控页面的的负载值呢?如下是一个三个节点的集群,从左侧cerebo提供的界面来看,load值标红,表明es的负载可能有点高了,那么这个具体达到什么值会显示红色呢,让我们一起来研究研究。


          IP属地:四川6楼2019-10-13 12:52
          回复



            IP属地:四川7楼2019-10-13 12:53
            回复
              先从主机层面说起,linux下提供了一个uptime命令来观察主机的负载


              IP属地:四川8楼2019-10-13 12:53
              回复
                其中load average的三个值,分别代表主机在1分钟、5分钟、15分钟内的一个负载情况。有人可能会疑惑,26.01是代表主机的负载在26%的意思吗,从我们跑的es集群情况来看,这显然不是负载很低的表现。其实啊,在单个cpu的情况下,这个值是可以看做一个百分比的,比如负载为0.05,表明目前系统的负荷为5%。但我们的服务器一般都是多个处理器,每个处理器内部会包含多个cpu核心,所以这里负载显示的值,是和cpu的核心数有关的,如果非要用百分比来表示系统负荷的话,可以用具体的负载值 除以 服务器的总核心数,观察是否大于1。总核心数查看的命令为:cat /proc/cpuinfo |grep -c 'model name'这台主机显示为24,从26的负载来看,目前处理的任务需要排队了,这就是为什么负载标红的原因。同时,这里列举一下,如何查看CPU情况
                总逻辑CPU数 = 物理CPU个数 X 每颗物理CPU的核数 X 超线程数# 物理CPU个数
                cat /proc/cpuinfo| grep "physical id"| sort| uniq| wc -l(我们的服务器是2个)
                # 查看每个物理CPU中core的个数(就是核数)
                cat /proc/cpuinfo| grep "cpu cores"| uniq(6核)
                # 查看逻辑CPU的个数
                cat /proc/cpuinfo| grep "processor"| wc -l
                (显示24,不等于上面的cpu个数 * 每个cpu的核数,说明是开启了超线程)


                IP属地:四川9楼2019-10-13 12:54
                回复
                  二、观察集群在 "忙什么"
                  通过tasks api可以直观的 观察到集群在忙什么?,包括父级任务,任务的持续时间等指标。命令如下:
                  curl -u username:pwd ip:port/_cat/tasks/?v | more


                  IP属地:四川10楼2019-10-13 12:54
                  回复
                    上面是我把副本设置为0后截的图。理论上还应该有一个bulk[s][r] 操作。可以看到目前写入很耗时,正常情况一批bulk操作应该是毫秒级的,这也从侧面说明了es的负载很高。从task_id、parent_task_id可以看出,一个bulk操作下面分为写主分片的动作 和写副本的动作。其中:
                    indices:data/write/bulk[s][p]:s表示分片,p表示主分片。
                    indices:data/write/bulk[s][r]:s表示分片,r表示副本。


                    IP属地:四川11楼2019-10-13 12:55
                    回复
                      简易的写入流程
                      如下是bulk请求的简易写入流程,我们知道客户端会选择一个节点发送请求,这个节点被之称为协调节点,也叫客户端节点,但是在执行之前,如果定义了预处理的pipline操作(比如写入前将key值转换,或者增加时间戳等),则此写操作会被拦截并进行对应逻辑处理。 从图中可以看出,写入操作会现根据路由出来的规则,决定发送数据到那个分片上去,默认情况下,是通过数据的文档id来进行路由的,这能保证数据平均分配到各个节点上去,也可以自定义路由规则,具体定义方式我们在下面会讲到。 接着,请求发送到了主分片上,主分片执行成功后,会将请求再转发给相应的副本分片,在副本分片上执行成功后,这个请求才算是执行完毕,然后将执行结果返回给客户端。 可以看出多副本在写多读少的场景下,十分的消耗性能,近似的,多了几个副本就相当于重复写了几份数据。如果不考虑数据容灾,则可以适当的降低副本数量,或者去掉副本,提高写入速度。在我们的集群里面并没有用到ingest角色类型的节点,这里提出来说也是为了便于大家更好理解各个节点的角色分工。


                      IP属地:四川12楼2019-10-13 12:55
                      回复