Kafka(一)概念,无状态和集群

概念

首先来说一下Kafka的基本大概念,分别有Broker,Topic,Partition,Producer,Consumer,ConsumerGroup。最简单的是Broker和Producer,一个Kafka节点就是一个Broker,多个Broker可以组成集群。然后是Topic和Partition,Topic是一个逻辑概念,Topic名相同就认为是同一个Topic,不用管是不是在同一个Broker下,而Partition是真正存消息地方,可以认为是传统MQ中队列的概念,注意,只是存消息,而非Broker原数据,每一个Partition对应一个存消息的CommitLog日志文件。之所以要在Partiton这个队列上加一层Topic逻辑概念,是因为,假如没有这一层逻辑概念,那么一个队列就只能在一台Broker上,不同Broker上的队列是没有任何关系的,在数据量很大的情况下,显然消息的存储是很受Broker的磁盘大小的限制的。当有了Topic后,数据可以被放在不同的Broker上的Partition,理论上一个Topic可以存任意多消息。当我们发消息时,如果仅仅指定Topic,那么消息会存在Topic中的某一个Partition上,前后不同的消息往往存在不同的Partition上,消费时失去了先后顺序,适合于非顺序消息消费。如果指定特定Partition来连续发消息,那么这个Partition中的消息就是有顺序的,并且需要消费者也指定某个Partition来进行消费,且ConsumerGroup只能有一个消费者,此时才能做到顺序消费,如果消费者订阅的是Topic那么还是轮询选一个Partition来消费,失去了先后顺序。总结一下,想做到顺序消费,有两种方案,一是topic层面,生成这发有顺序要求的消息到topic,但topic只有一个partition,消费者订阅消息且该消费组只有他一个消费者,订阅同一个topic的消费者组可以有多个,后面介绍,二是partition层面,topic可以有不同分区,发顺序消息到topic下的特定partition,消费者定义的是partition,同样该组只能有他一个。Topic是一个大的队列,能存的消息可以在不同broker上,容量是理论无限的,作为整体提供服务时,但消息是没有顺序的。Partition是大队列中的小队列,只能在一个broker上(副本除外),容量是优先的,但消息是有顺序的。

消费者组

提到了这么多次消费者组,就来说一下消费者组的概念吧。他也是逻辑概念,如果说topic是为了解决将消息放在不同broker的问题,那么消费者组就是用来实现具体消息的分发模式的。传统的MQ是有两种模式的,一是queue队列模式,即一条消息只能被一个消费者消费,二是发布订阅模式,即一条消息被广播到多个消费者。Kafka就是巧妙通过消费者组来实现这两个模式的,每个消息可以被广播到多个消费者组,而消费者组中只有一个消费者实例能够消费到这个消息。有了这两条规则,就能实现队列模式和发布订阅模式了。如果所有订阅了同一个partition的consumer在同一个消费者组就,就是队列模式,如果每个consumer都自成一组,那么就是发布订阅模式。注意所谓的队列模式并不是同一个组中的消费者随机消费,而是有消息分配策略的TODO

消息存储

有了这些基本概念后,来着重介绍一下Kafka的消息存储,之前说了消息是实际存放在Partition下的,再具体就是一个Partition对应一个commitLog,消息就存在commitLog中,每创建一个分区,不管有没有数据,其commitLog都是1个G的大小,为啥这个队列这么大呢,因为Kafka的消息被消费后是不会删除的,默认保留七天,时间可是通过参数设短一点,节约磁盘。因为不删除,所以引入了一个offset偏移量的概念,commitLog用他来控制消费进度,而offset是由consumer来维护的,也就是每个消费者可以维护自己的offset,用来控制自己从哪开始消费,而且新的消费者来监听含有消息的partition时,其offset默认是最新消息的offset,是收不到旧消息的,除非指定offset,甚至可以从头开始消费。此时有个问题,既然offset是存在消费者的,那消费者消费到某一位置时挂掉,重启消费者,他咋知道从哪开始呢?TODO

无状态

之前提到kafka的无状态,再来细说,因为offset不由broker自己维护,broker只管consumer给他offset后的返回,所以consumer对broker的影响是很小的,添加或者减少一个consumer,对其他consumer是没有影响的,因为没有consumer维护自己的offset,所以说Kafka是无状态的,性能不会因为consumer数量增加而减少太多。那访问压力去哪了呢?TODO不光是consumer的扩容很容易,集群状态下broker的扩容也很容易,因为Kafka将无状态贯彻到底,所有的关键信息都放在zk中,kafka连上zk后,会存很多节点,比如集群后的/brokers/下有ids,topics,seqid。其中ids存放broker集群后的ID(1,2,3),topics存放所有的topic(order,test1,test2)。更深的,/brokers/topics/{order}/partitions/,存放主题下的partition(0,1),继续深,/brokers/topics/{order}/partitions/{0}/state,state文件存的是partition0对应的leader信息,isr同步副本信息。所以kafka的元信息都是zk来维护的,所以kafka完全是无状态的,水平扩容很容易,因为不需要与其他kafka交互来同步元数据信息,元数据全部从zk去取,只要读zk就可以了。

搭建集群

既然提到kafka的无状态有利于集群,那就来说一下kafka的集群相关概念吧。搭建集群时很简单,和redis一样,只需要改好配置文件即可,配置文件中和集群相关的也只有brokerID和listener,分别配置的ID和本机的IP即可。当kafka是集群状态时,我们创建topic时就多了一个参数,就是副本因子,集群还会影响到partition和partition副本的所在broker位置。之前说partition只能在一台Broker上是不准确的,因为partition可有有副本,所有副本同名,副本是存在不同的broker上的,但是多个副本中只有一个leader能够进行接收消息和发送消息,这和redis,zk是不同的,后两者的集群往往是leader提供写,follower提供读。但kafka不同,副本只是用来复制leader的结果,相当于是一个消费者罢了,其实我觉得拿来读好像也可以TODO。上面所说的是同一个partition的不同副本分配在不同的broker下,而且指定的副本因子要小于等于broker数,目的是容灾,不能一个broker挂后整个partition消失。而同理,不同的partition也是分配在不同的broker下,目的也是容灾,不能一个broker挂后整个topic失效。集群绕不开的同步和通信问题,都被绕开了,因为他无状态。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值