kafka入门篇

kafka入门篇

    此前介绍了rabbit mq作为消息中间件的一些设计架构理念以及其轻便小巧的特点,详见一文快速入门RabbitMQ。这次来介绍下性能极其恐怖的另一个消息中间件kafka。

    kafka最初并不是用来做消息中间件的,它的初衷是提供一个日志收集服务,对来自各个服务的海量日志进行快速存储,然后通过特定的日志分析服务再去kafka上获取这些日志。所以kafka最大的特点是极其高的吞吐量,因为日志的分析不需要很高的实时性,所以kafka在延迟方面做的不够优秀,毕竟定位不在此。所以对于一些特定的场景,kafka可以发挥最大的作用。当然也可以作为消息中间件来使用。

    kafka的设计目标造就了kafka的优势所在,所以先来谈一谈kafka的设计目标:

    1、kafka要存取海量数据,所以对于海量消息的持久化和读取速度要快,不管多大的数据量,存取时间复杂度都是O(1)。

    2、高吞吐,随便一台低性能的电脑都可以做到单机秒十万级别,如果性能优秀加上优化措施,kafka的最大吞吐量达到2000w/s

    3、消息支持分区、kafka要支持集群、分布式部署,单节点支持上千客户端连接,保证高可用,数据零丢失。所有集群支持动态扩展。

    4、支持离线处理和实时处理。

    5、支持多语言客户端。

    所以总结一下,kafka的特点就是突出一个快,而且“能装货”。保证可以快速存储海量消息,同时支持快速读取海量消息。我们都知道数据要存储磁盘是效率很低的事,kafka偏偏反其道而行之,既要满足消息持久化,同时又要做到快速存取。而这,正是kafka的强之所在。

    对于不了解kafka的人而言,路得一步一步走,这篇文章标题既然是入门篇,所以重点还是介绍kafka的一些基本概念和架构。高级特性或涉及进阶部分放到另外的篇幅去介绍。

基本概念

kafka无论作为消息中间件还是日志收集分析系统,都离不开三个主要部分:生产者、消费者、以及broker(集群)。一言蔽之:生产者要连接到kafka实例生产消息,kafka将消息存储落盘,消费者连接kafka获取消息。broker就是kafka的实例,可以单机,也可以集群。

对于生产者来讲,我需要知道消息将要发到哪个broker集群,同时还得指定一个topic主题,主题提前在broker中定义,一个topic存放同一类型的消息,可以理解为数据库中的一个逻辑表。有了topic,在topic下面需要配置partition分区。同一个topic下的不同partition共同存储topic下的所有消息。对于单机broker来说,只需要一个partition即可。对于集群来说,broker会把同一个topic下的不同partition放到不同的机器上。消息进入topic后要放到哪个集群,可以配置指定,也可以让其轮询,甚至自定义。在同一个partition内,消息是有序的。

图片

一条消息只会放到一个partition中。如果要保证高可用,需要另一个概念就是Replicas,他表示分区的副本,通过配置,可以对每个分区设置副本,这时候partition就有两种:leader和follower,leader负责接收生产者的消息,并提供给消费者,follower在正常场景下只会去同步leader的消息,不提供读写,而且follower一定不会和leader在同一台机器。当某个broker挂掉,如果上面有leader分区,集群会自动在这个分区的follower分区中选举一个leader继续提供服务。

有了生产者把消息放入kafka,就需要有消费者来消费,对于消费者来说,主要涉及两个概念:消费者和消费者组。

图片

消费者通过偏移量来消费消息,同一个topic可以被多个消费者组去消费。但是对于一个消费者组来说,如果一个消费者组内有多个消费者,broker会把topic中的partition分配给消费者,其规则为:一个partition只能有一个消费者消费,如果分区数大于消费者数,会出现一个消费者消费多个分区的情况,如果分区数和消费者数刚好一样,那就会给每个分区分配一个消费者,如果分区数小于消费者数,则会有一部分消费者闲置,得不到消息。这个机制保证同一个消费者群组中,不会有消费者重复消费同一个partition。

对于broker集群,正常情况下也会选出一个broker的leader,然后每个分区如果设置了副本数>1,分区也会有各自的leader,刚刚已经说过,分区只有leader提供正常的生产消费,其他的follower只从leader同步数据。

图片

最后介绍一下消息的批次,kafka为了提高消息的传输效率,会对消息进行压缩,但是不会每条消息都压缩一次然后发送。对于同一个partition的消息,kafka会先进行缓存,等消息数量达到一定程度后,把这些消息作为一个批次进行打包压缩再发送。这是kafka吞吐量大的核心秘密所在。

生产消费流程

消息生产流程:

消息生产主要由两个线程负责,一个主线程,一个sender守护线程。主线程负责消息的封装,然后会经过拦截器、序列化器、分区器,之后存放到缓冲区。此时主线程的任务就完成了。如果在消息发送时配置acks=0,这时候就直接返回给客户端了。

另一个sender线程在一定条件时会从缓冲区收集消息,进行格式转换后再进行缓存,等待broker负载小的时候,发送消息到broker。返回结果给主线程,这时如果结果是失败,主线程通过retries参数决定是否重试。

在这整个过程中,有两个参数至关重要,一个acks,一个retires,这决定了消息是否丢失。同时在重试时有可能会出现消息乱序,需要其他参数配合保证消息有序性,这里先大概提一嘴,高级的东西放到后面的文章篇幅单独介绍。总之生产者的流程大概就是这样,不管客户端是同步方法还是异步方法,在kafka内部都是异步的通过sender线程去异步发送的。

消息消费流程:

消费流程就比较简单,kafka中的消费只能通过拉取,不提供推模式。消费者需要主动调用方法去kafka中获取消息,同时会获取消息的元数据。值得一提的就是消费时需要配置一个参数来指定偏移量的提交策略。以及当从broker消费时,没有获取到消费偏移量时要如何处理。前面已经提过消费者是通过偏移量去消费指定的分区,而消费者的偏移量是保存在kafka的(也可以存在zk,但不推荐),这就需要消费者把自己消费到哪里了提交给kafka,这样如果一个消费者挂了,另一个消费者接手后仍然知道上一个消费者已经消费到哪里。这个提交策略可以手动提交,也可以自动提交,可以同步,也可以异步。这有可能导致消息的重复消费。比如提交策略定为5秒一次,上一次消费者提交偏移量是100,然后在之后的3秒内又消费了20,偏移量来到了120,这时消费者挂了,120的偏移量还没提交到kafka,消费者重启或者被接管后,就又从100开始消费了。

还有个情况是一个分区已经有很多的消息了,这时消费者通过一个新的消费者组连接到这个topic去消费,要从哪里开始消费呢?是从头还是从当前生产者生产到的位置?还是直接抛异常,这些都是通过参数来控制。

以上就是kafka入门篇的全部知识点了,至于高阶的比如:消息重复、消息丢失、集群选举、生产者和消费者的参数、kafka的再均衡这些高级概念每个单独拎出来都可以写一篇文章了,所以这些问题都放到别的文章中单独介绍吧。

 

 

 

不与三季人说
收录于合集 #中间件
 2
上一篇一文快速入门RabbitMQ
阅读 66
不与三季人说
22篇原创内容
 
posted @ 2023-07-04 10:07  往事已成昨天  阅读(54)  评论(0编辑  收藏  举报