前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >大数据系列之----海量数据下是kafka设计和实战演练

大数据系列之----海量数据下是kafka设计和实战演练

作者头像
源哥
发布2019-05-15 14:17:53
4170
发布2019-05-15 14:17:53
举报
文章被收录于专栏:源哥的专栏源哥的专栏

       网上有很多Kafka的文章,但大多写得千篇一律,要么偏理论化,无实战数据参考。要么写了发现的某个问题的解决方案,对于想在实际环境上搭建真实的Kafka环境,参考意义并不大。

       这篇文章基于大量的实战经验,在大规模,海量数据,以及实时处理的环境下,这些经验也是在解决Kafka很多真实问题得出的。试图在一开始就协助大家在大家在搭建真实Kafka环境的时候,提前做好最优的解决方案,避免后续不断的出各类问题,然后投入大量人力进行整改。

       这篇文章不是给完全的初学者准备的,文章并不会针对索引的细节给出一步步的解决,所以,读者如果对一下基本概念不熟悉的话,建议提前阅读相关文档。

      先来解答一下到底是要选择Kafka还是像RabbitMQ、RocketMQ、ActiveMQ等其他消息队列?

      首先,在大数据环境下,首选一定是Kafka,批量的日志采集,大量的数据同步等,Kafka的性能极其高。

      但是如果企业已经有了Kafka,还需要用RabbitMQ、RocketMQ、ActiveMQ等其他消息队列,还是直接就采用Kafka进行业务消息的处理呢?

      那就要看业务的,Kafka经过最近几年发展,可靠性方面已经大幅提升,其可靠性可能并不逊色于RabbitMQ。但是我们也知道,Kafka原先是为了日志而生,而为了提高可靠性,需要进行多种配置,比如说,acks配置为-1,增加副本数,写入采用同步等,这个为了提高可靠性而配置,则降低了吞吐率,导致性能并不比RabbitMQ高。

      而且在我们的使用中,Kafka在极端情况下,还是出现了极少量的数据丢失,这类问题极难跟踪追查。而RabbitMQ、RocketMQ、ActiveMQ等其他消息队列则一直比较稳定,几乎不用担心数据丢失问题。而且Kafka稳定性要稍弱一点,维护也相对复杂一点。

      所以我建议在正常的业务场景下,对性能要求不是特别高的情况下,但是首选RabbitMQ、RocketMQ、ActiveMQ等消息队列。而假设企业已经有Kafka,而且业务并非像银行等对安全要求极其高的业务,允许极端情况下的极少量数据丢失,且企业对Kafka应用比较熟悉,那也可以选择Kafka作为业务的消息队列。

      解决了选择问题,那么现在就来谈谈配置问题。

      生产者的发送方式应该设置为同步还是异步?我相信这是很多人纠结的地方,而且选择一种方式之后,后续如果想改动就没有那么容易了,往往涉及到代码的改动,如果现网项目是维护很久了,以前的人写了,新的开发人员往往不敢改动这里的配置,生怕发生异常。

      默认的发送方式是同步的,但如果改成异步,将极大的提高性能。但异步方式却不能确保消息的可靠性,增加了丢数据的风险。

      先来看看异步方式配置,有下面几个参数:

​​​​

      异步方式,可以批量发送消息,并且有设置超时和重试机制,但系统重试超过限制,消息会丢失,不过Kafka0.11版本有回调机制,如果消息发送失败,可以回调,然后由业务觉得下一步处理。

      我曾经遇到过因为Kafka的Bug,导致kafka的其中一个broker有一段时间不可用,导致消息发送失败。理论上,对于这部分失败,通过把失败信息记录下来,然后通过重刷数据修复。

      但是这个回调机制其实是不能100%保证绝对有回调的,正常情况下是没有对应的,但是在某种极其特殊的异常情况下,Kafka本身出现问题了,有可能是无法回调的。

      由于异步方式性能极高,所以业界使用异步方式还是占多数的,所以建议对消息可靠性要求不是极其严格的话,采用异步方式,重试30秒如果失败就回调,这样性能上基本也是可以满足的。

      接下来再来讲一讲acks,这边是用来表示可靠性级别的配置,一般有0,1和-1三种配置,默认配置是1。0表示消息发送不等待Leader的确认就继续发送下一条,1表示等待Leader确认后再发下一条,-1表示等待Leader和Follower确认后再发下一条。配置为0极其不可靠,我觉得几乎不用考虑。主要是考虑配置为1和-1的情况。

      我们假设就是3副本,也就是说有1个Leader和2个follower,配置为1,也就是说消息写入Leader成功后就返回,这时候,Leader的数据会同步给2个follower,但假设这个时候Leader突然间宕机了,这时就会发生消息丢失。

      当配置为-1时,则还有另外一个参数,用来标记多少个follower同步成功后,继续下一条消息的发送。假设消息写入Leader成功后,但follower还在同步,此时Leader挂掉,由于消息还没有得到确认,所以该消息会重新发送,并不会丢失。

      设置为-1并不消息消息就一定不会丢失,如果Leader挂掉,重新选举的Leader也挂掉,也就是连续两个Leader都挂掉,是有可能出现消息丢失的。而且,设置为-1可能会产生另外一个问题,就是消息重复,比如说,消息同步Leader成功,同步Follower1成功,但还没来得及同步Follower2,这是Leader宕机,Producter重新发送消息,这是Follower1就重复接受到同一条消息了。

      讲了那么多,那配置为1是不是表示就不安全呢?其实大部分情况下是安全的,比如说集群出现故障,其中一个broker挂掉了,consumer端会产生一系列INFO和WARN级别的日志输出,但若干秒之后自动恢复,消息还是连续的,并没有出现断点。

      这边遇到过两次消息丢失的情况,一次是因为Kafka的Bug,导致ISR收缩为自己,并且不可用,导致消息丢失。另外一次是因为网络短时间不可用,导致消息丢失。

      但是如果acks设置为-1,对性能影响挺大,因为写完Leader之后,要有同步follower,所以相比acks设置为1,可能性能会下降一半。

      所以在设置acks配置的时候,如果只是采集日志,可以接受极少量的数据丢失,那么建议把acks配置为1。

      如果是业务数据,那么要根据情况看,如果能够接受该增加一倍的硬件成本,那么建议配置为-1,如果能接受极少量的数据丢失,那么可以配置为1。实际使用中,出现消息丢失的情况极难出现,大部分都是业务自身代码的问题导致的。

      接下来讲一下副本数吧,建议正常还是采用三副本(就是1个Leader,2个Follower),三副本是比较常用的做法,三副本才是认为可靠的。当然,副本超过3个,那更好,只不过存储成本就高利了,而且提高的可靠性并没有那么明显。而把副本从2个改成三副本,则可靠性提高很多,不推荐设置为2副本。

      接下来将讲讲consumer这边。

      commit方式有自动提交和手动提交两种方式,默认是自动提交,提交间隔5秒。

      自动提交有数据丢失和数据重复的风险,比如说,消息自动提交了,但consumer还没有处理完就挂掉了,那么数据就没有处理完成而丢失了。如果消息处理完成了,但还没来得及提交,系统就挂掉了,那么就会出现数据重复。

      但是手动提交也有问题,正常来说,consumer和partition的个数并不一致,而consumer的提交是针对partition的,那么当多个任务对应同一个partition的时候,一个提交就会把别的还在处理的任务也commit了。

现在的consumer通常有两种写法:

  1. 设置多个consumer,每个consumer就是一个进程
  2. 设置1个consumer,对应多个线程

      第一种方式,consumer的数量不能超过partition的数量,否则多出来的consumer永远不会被用到,而且因为每个consumer都需要一个TCP连接,会造成大量的性能消耗。第二种方式,实现每个partition的消息顺序处理更困难,比如说两个消息被不同的线程处理,那么处理上就可以突破时间顺序,导致后到的数据被提前处理。

      通常来说,更多推荐的是采用方式2,它更加容易扩展,性能不够了,扩大线程数量就可以了。

      但是,手动提交上面也说了,当多个任务对应同一个partition的时候,一个提交就会把别的线程还没有提交的任务commit了。

      综上所述,如果对于消息丢失和重复的要求不是特别高的话,建议还是采用自动提交方式把,它实现简单,逻辑比较健壮。如果对可靠性要求非常高,那么还是采用手动提交的方式,但是就要在处理是就要很注意。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019年05月09日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
消息队列 CMQ 版
消息队列 CMQ 版(TDMQ for CMQ,简称 TDMQ CMQ 版)是一款分布式高可用的消息队列服务,它能够提供可靠的,基于消息的异步通信机制,能够将分布式部署的不同应用(或同一应用的不同组件)中的信息传递,存储在可靠有效的 CMQ 队列中,防止消息丢失。TDMQ CMQ 版支持多进程同时读写,收发互不干扰,无需各应用或组件始终处于运行状态。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档