老吴的学习笔记-kafka

  • 听说kafka是个神器。好想学!


    老吴的学习笔记-kafka_第1张图片

kafka是啥?

  • 分布式消息队列
老吴的学习笔记-kafka_第2张图片
  • 排队用的。
老吴的学习笔记-kafka_第3张图片
  • 在分布式系统中,消息队列(message queue)是实现生产者消费者模式的利器!
  • 生产者(producer)把只管把生产好的消息无脑往队列里放,快慢都可以跟着感觉走。随放随走,不粘人。
  • 消费者(consumer)有需求了就只管从队列里取,取多取少请你随意。
  • 市场不景气供大于求,生产者依然可以随意生产,消息队列hold得住。
  • 消费者信心恢复的时候,它来会来处理陈年旧货。
  • 我盗一张图给你看:


    老吴的学习笔记-kafka_第4张图片
    http://kafka.apache.org

全世界的消息队列都死光了吗,偏偏要学kafka?

  • 此言差矣。我中意kafka是因为:
  • 吞吐量高的吓人
  • 可靠性高的要命
老吴的学习笔记-kafka_第5张图片

我懂的不多,你不我骗我。要保证可靠性,消息都是要存储在硬盘上的,就硬盘那点速度,怎么可能吞吐量高?

  • 硬盘速度不快,因为时间都浪费在磁盘寻道上了!东写一下,西写一下,磁头在磁盘上疲于奔命,根本没有多少时间是用在写入上的。

既然这样,我让磁头不要动来动去,待在一个地方死命写不就完了?我好机智。话说这样以后卵用是否明显?

  • 据kafka官网吹,如果随机写入磁盘,速度就只有100KB每秒。顺序写入的话,7200转/s的磁盘就能达到惊人的600MB每秒!
老吴的学习笔记-kafka_第6张图片

然后呢?

  • 然后他们就决定直接往磁盘里写,不缓存了!
老吴的学习笔记-kafka_第7张图片

太草率了吧?!

  • 是真的!因为他们发现操作系统对文件访问做了优化,文件会在内核空间分页做缓存(pageCache)。写入时先写入pageCache。由操作系统来决定何时统一写入磁盘。操作系统很鸡贼地使用顺序写入,速度杠杠的!想想看看,每秒600MB,折合为带宽就是4.8G !千兆以网的速度也不过如此啊。

如此来看,kafka对数据的“吞”入速度确实不错。不过我很好奇,如果我们服务器的硬盘很烂,又或者带宽不高,一台机器处理不过来,kafka如何扩展?

  • 分而治之。不同业务的消息用topic区分开来。一个topic的消息可以发到多个partition(队列分组)。这些partition部署在不同的机器上。producer在投递一个消息之前,可以自由选择要投递到哪个partition. 选择方法就很多啦,你可以轮流着来(round robin),也可以逮着一个天天来,还可以根据消息的特征来。性能不够,加机器,加partition啦。

吞吐量,量只是一个方面。我想知道kafka在量上是如何保证的?

  • 说来话长。我长话短说:通过pull模式消费消息。
老吴的学习笔记-kafka_第8张图片

能否说细一点?

  • 是这样的,同一个topic的消息,可能会有多个业务集群都很感兴趣。每个集群都希望得到这份消息。而同一个集群内部绝大部分情况下只需要消费此消息一次。
  • 如果采用push的模式,需要消息队列将每个消息广播到所有集群中。并且只从每个集群中选择一台机器来接收此消息。
  • 如果每个集群消费的速度不同,那么消费的进度也不同。需要消息队列来跟踪每个集群的消费进度和消费速度,以决定是否push下一条消息。
  • 如果采用pull的模式,能否消费下一条消息完全由消费者决定。消息队列只需要被动地记录每个集群的消费进度即可。
  • 在这基础上,消费者根据自身能力一次拉取多个消息并采用压缩的格式传输就很自然啦。

我明白了。采用pull的方式消费,那么消费者之间不会因为消费速度不一致而互相干扰。消费最快的消费者的速度不会受到任何约束。因此,kafka 对消息的量也就达到了极致。

说到消费模式,我想知道消费者是如何消费的?

  • 消费者会自主选择从哪个partition消费。partition内的消息是按生产顺序排列的。如果需要消费时消息的顺序不能乱,需要固定在一个partition消费。

说了老半天,最重要的问题给忘了。kafka中的producer、customer、partition是如何发现彼此的呢?producer怎么知道消息投递到哪些partition?consumer又是如何知道从哪些partition获取消息?

  • 当然是集群组织利器:ZooKeeper! 集群中的各参与者将自己注册到ZooKeeper中,从ZooKeeper中发现彼此。详情请参见:老吴的学习笔记-Zookeeper

啊!~~不行了,我感到自己的知识快要溢出了!

老吴的学习笔记-kafka_第9张图片

少年且慢,还有一事相问。刚才只说了吞吐量,来说说可靠性吧!

  • 可靠交付包括三个部分:从producer交付到parition的可靠性,在partition内部的可靠性,从partition到consumer的可靠性。
  • 接下的精华部分你可要认真听了。

请说重点。producer到partition怎么个可靠法?

  • 是这样的,消息在producer内部,因为producer自己失败而丢失这种事情,kafka并不管。
  • 在向partition提交(commit)消息时,partition会先将消息持久化到文件中。
  • 这还不够。如果这时候kafka的这一台机器挂了呢?所以这时候这份消息还不能被消费。
  • 为了提高可靠性,kafka支持为每个partition(leader)设置备份parition(follower). 可以设置多个。
  • follower唯一的职责,就是消费leader中的所有消息,并持久化在自身的队列中。
  • 当超过一半的parition(包括follower和leader)都存储了消息之后,leader partition向producer返回ack, 表示消息接收成功。
  • 所以,只要kafka向producer承诺了交付,消息就基本丢不了。只有当超过一半的机器(follower + leader)同时失效,消息才会丢失。

如果partition存储消息成功,在向producer放送ack时网络错误怎么办?

  • 这时producer并不知道消息是否可靠到达parition,只有选择重发。
  • 当partition再次收到同一条消息时,不能确定此消息是重发的,还是全新的。所以只有硬着头皮再存一遍。
  • 因此,kafka中,消息是可能重复的。虽然可以通过让producer生成一个唯一id的方法来解决此问题,但当前版本的kafka没有这样做。

在partition内部如何可靠?

  • 实际上producer在向parition发送消息时,消息已经得到了可靠的存储。
  • 当leader partition失效时,kafka会从备份partition中选举一个新的leader继续提供服务。

从partition交付到consumer如何可靠?

  • 当消费者拉取一条消息时,有两种选择。
  • 一是先向kafka回复说:”我已经成功消费了“,然后再执行业务逻辑
  • 二是先执行业务逻辑,然后通知kafka ”我已经成功消费“
  • 如果使用第一种方法,那么如果在执行业务逻辑的过程中异常,则会造成消息丢失的情况。kafka对此并不知情。
  • 如果采用第二种方法,那么如果业务执行失败,则kafka无法收到消费确认的ack。由于kafka并不能确定是因为业务逻辑失败,还是因为网络问题导致ack消息没有收到,因此下一次消费时会重新消费此消息。这就导致同一个消息被重复消费两次。

那么消息的重复消费怎么解决呢?

  • 还是老方法,通过id进行幂等。当消息被消费第二次时,发现已经消费过了,则不再执行,直接返回执行成功即可。

你可能感兴趣的:(老吴的学习笔记-kafka)