kafka集群基于可用性指标进行性能调优实践-kafka 商业环境实战

版权声明:本套技术专栏是作者(秦凯新)平时工作的总结和升华,通过从真实商业环境抽取案例进行总结和分享,并给出商业应用的调优建议和集群环境容量规划等内容,请持续关注本套博客。期待加入IOT时代最具战斗力的团队。QQ邮箱地址:[email protected],如有任何学术交流,可随时联系。

1 掉下来一个可用性

  • 可用性反映了kafka集群应对崩溃的能力,调优可用性就是为了让Kafka更快的从崩溃中恢复过来。

2 Topic角度看问题

  • Controller就是broker,主要负责副本分配方案和分区上线的工作(根据副本的分配方案)。
  • 副本状态机
  • 分区状态机
  • 注意Topic的分区数越多,一旦分区的leader副本所在broker发生崩溃,就需要进行leader的选举,虽然Leader的选举时间很短,大概几毫秒,但是Controller处理请求时单线程的,controller通过Zookeeper可实时侦测broker状态。一旦有broker挂掉了,controller可立即感知并为受影响分区选举新的leader,但是在新的分配方案出来后,发布到各个broker进行元数据更新就要浪费网络I/O了。
  • 建议分区不要过大,可能会影响可用性。

3 Producer角度看问题

  • 首推参数是acks,当acks设置为all时,broker端参数min.insync.replicas的效果会影响Producer端的可用性。该参数越大,kafka会强制进行越多的follower副本同步写入日志,当出现ISR缩减到min.insync.replicas值时,producer会停止对特定分区发送消息,从而影响了可用性。
  • 版权声明:本套技术专栏是作者(秦凯新)平时工作的总结和升华,通过从真实商业环境抽取案例进行总结和分享,并给出商业应用的调优建议和集群环境容量规划等内容,请持续关注本套博客。期待加入IOT时代最具战斗力的团队。QQ邮箱地址:[email protected],如有任何学术交流,可随时联系。

4 Broker角度看问题

  • Broker端高可用性直接的表现形式就是broker崩溃,崩溃之后leader选举有两种:1:从ISR中选择。2:通过unclean.leader.election.enable值决定是否从ISR中选择。第二种情况会出现数据丢失的风险。
  • 另一个参数是broker崩溃恢复调优,即num.recovery.threads.per.data.dir。场景是这样的,当broker从崩溃中重启恢复后,broker会扫描并加载底层的分区数据执行清理和与其他broker保持同步。这一工程被称为日志加载和日志恢复。默认情况下是单线程的。假设某个Broker的log.dirs配置了10个日志目录,那么单线程可能就吭哧吭哧扫描加载,太慢了。实际使用中,建议配置为日志的log.dirs磁盘数量。

5 Consumer角度看问题

  • 对于Consumer而言,高可用性主要是基于组管理的consumer group来体现的,当group下某个或某些consumer实例“挂了”,group的coordinator能够自动检测出这种崩溃并及时的开启rebalance,进而将崩溃的消费分区分配到其他存活的consumer上。

  • consumer端参数session.timeout.ms就是定义了能检测出failure的时间间隔。若要实现高可用,必须设置较低的值,比如5-10秒。一旦超过该值,就会开启新一轮的reblance。

  • 消息处理时间参数很牛,max.poll.interval.ms,参数设置了consumer实例所需要的消息处理时间,一旦超过该值,就是高负荷状态,此时consumer将停止发送心跳,并告知coordinator要离开group。消费者在创建时会有一个属性max.poll.interval.ms, 该属性意思为kafka消费者在每一轮poll()调用之间的最大延迟,消费者在获取更多记录之前可以空闲的时间量的上限。如果此超时时间期满之前poll()没有被再次调用,则消费者被视为失败,并且分组将重新平衡,以便将分区重新分配给别的成员

  • hearbeat.interval.ms 当coordinator决定开启新一轮的reblance时,他会把这个决定以REBALANCE_IN_PROCESS异常的形式塞进consumer心跳的请求响应中,这样就可以飞快的感知到新的分区分配方案。

  • kafka调优经典的独白,哈哈哈哈:

      上线两个月都没有问题,为什么最近突然出现问题了。我想肯定是业务系统有什么动作,我就去问了一个下,
      果然头一天风控系统kafka挂掉了,并进行了数据重推,导致了数据阻塞。但是我又想即使阻塞了也会慢慢消费掉啊,不应
      该报错呀。后来我看了一下kafka官网上的参数介绍,发现max.poll.records默认是2147483647 
      (0.10.0.1版本),也就是kafka里面有多少poll多少,如果消费者拿到的这些数据在制定时间内消费不完,就会手动提交
      失败,数据就会回滚到kafka中,会发生重复消费的情况。如此循环,数据就会越堆越多。后来咨询了公司的kafka大神,他
      说我的kafka版本跟他的集群版本不一样让我升级kafka版本。于是我就升级到了0.10.2.1,查阅官网发现这个版本的max.po
      ll.records默认是500,可能kafka开发团队也意识到了这个问题。并且这个版本多了一个max.poll.interval.ms这个参数,
      默认是300s。这个参数的大概意思就是kafka消费者在一次poll内,业务处理时间不能超过这个时间。后来升级了kafka版本
      ,把max.poll.records改成了50个之后,上了一次线,准备观察一下。上完线已经晚上9点了,于是就打卡回家了,明天看
      结果。第二天早起满心欢喜准备看结果,以为会解决这个问题,谁曾想还是堆积。我的天,思来想去,也想不出哪里有问题
      。于是就把处理各个业务的代码前后执行时间打印出来看一下,添加代码,提交上线。然后观察结果,发现大部分时间都用
      在数据库IO上了,并且执行时间很慢,大部分都是2s。于是想可能刚上线的时候数据量比较小,查询比较快,现在数据量大
      了,就比较慢了。当时脑子里第一想法就是看了一下常用查询字段有没有添加索引,一看没有,然后马上添加索引。加完索
      引观察了一下,处理速度提高了好几倍。虽然单条业务处理的快乐, 
      但是堆积还存在,后来发现,业务系统大概1s推送3、4条数据,但是我kafka现在是单线程消费,速度大概也是这么多。再
      加上之前的堆积,所以消费还是很慢。于是业务改成多线程消费,利用线程池,开启了10个线程,上线观察。几分钟就消费
      完了。大功告成,此时此刻,心里舒坦了好多。不容易呀!
    复制代码

6 参数清单

Broker端

  • 避免过多分区
  • 设置unclean.leader.election.enable=true(为了可用性,数据丢失不考虑)
  • 设置min.insync.replicas=1(减轻同步压力)
  • 设置num.recovery.threads.per.data.dir=broker 日志的log.dirs磁盘数

Producer端

  • 设置acks=1,设置为all时,遵循min.insync.replicas=1

consumer端

  • 设置session.timeout.ms为较低的值,比如100000
  • 设置max.poll.interval.ms消息平均处理时间,可适当调大。
  • 设置max.poll.records和max.partition.fetch.bytes减少消息处理总时长,避免频繁的rebalance。
  • 版权声明:本套技术专栏是作者(秦凯新)平时工作的总结和升华,通过从真实商业环境抽取案例进行总结和分享,并给出商业应用的调优建议和集群环境容量规划等内容,请持续关注本套博客。期待加入IOT时代最具战斗力的团队。QQ邮箱地址:[email protected],如有任何学术交流,可随时联系。

7 总结

num.recovery.threads.per.data.dir以及max.partition.fetch.bytes以及max.poll.records重点关注一下,很有意思的选手。

秦凯新 于深圳 201812042237

版权声明:本套技术专栏是作者(秦凯新)平时工作的总结和升华,通过从真实商业环境抽取案例进行总结和分享,并给出商业应用的调优建议和集群环境容量规划等内容,请持续关注本套博客。期待加入IOT时代最具战斗力的团队。QQ邮箱地址:[email protected],如有任何学术交流,可随时联系。

你可能感兴趣的:(kafka集群基于可用性指标进行性能调优实践-kafka 商业环境实战)