全网最通俗易懂的Kafka入门( 二 )


红色块的partition代表的是主分区,紫色的partition块代表的是备份分区 。生产者往topic丢数据,是与主分区交互,消费者消费topic的数据,也是与主分区交互 。
备份分区仅仅用作于备份,不做读写 。如果某个Broker挂了,那就会选举出其他Broker的partition来作为主分区,这就实现了高可用 。
另外值得一提的是:当生产者把数据丢进topic时,我们知道是写在partition上的,那partition是怎么将其持久化的呢?(不持久化如果Broker中途挂了,那肯定会丢数据嘛) 。
Kafka是将partition的数据写在磁盘的(消息日志),不过Kafka只允许追加写入(顺序访问),避免缓慢的随机 I/O 操作 。

  • Kafka也不是partition一有数据就立马将数据写到磁盘上,它会先缓存一部分,等到足够多数据量或等待一定的时间再批量写入(flush) 。
上面balabala地都是讲生产者把数据丢进topic是怎么样的,下面来讲讲消费者是怎么消费的 。既然数据是保存在partition中的,那么消费者实际上也是从partition中取数据 。
全网最通俗易懂的Kafka入门

文章插图
从各个主分区取数据
生产者可以有多个,消费者也可以有多个 。像上面图的情况,是一个消费者消费三个分区的数据 。多个消费者可以组成一个消费者组 。
全网最通俗易懂的Kafka入门

文章插图
消费者组
本来是一个消费者消费三个分区的,现在我们有消费者组,就可以每个消费者去消费一个分区(也是为了提高吞吐量)
全网最通俗易懂的Kafka入门

文章插图
消费者组的每个消费者会去对应partition拿数据
按图上所示的情况,这里想要说明的是:
  • 如果消费者组中的某个消费者挂了,那么其中一个消费者可能就要消费两个partition了
  • 如果只有三个partition,而消费者组有4个消费者,那么一个消费者会空闲
  • 如果多加入一个消费者组,无论是新增的消费者组还是原本的消费者组,都能消费topic的全部数据 。(消费者组之间从逻辑上它们是独立的)
前面讲解到了生产者往topic里丢数据是存在partition上的,而partition持久化到磁盘是IO顺序访问的,并且是先写缓存,隔一段时间或者数据量足够大的时候才批量写入磁盘的 。
消费者在读的时候也很有讲究:正常的读磁盘数据是需要将内核态数据拷贝到用户态的,而Kafka 通过调用sendfile()直接从内核空间(DMA的)到内核空间(Socket的),少做了一步拷贝的操作 。
全网最通俗易懂的Kafka入门

文章插图
Kafka 读数据 巧妙
有的同学可能会产生疑问:消费者是怎么知道自己消费到哪里的呀?Kafka不是支持回溯吗?那是怎么做的呀?
  • 比如上面也提到:如果一个消费者组中的某个消费者挂了,那挂掉的消费者所消费的分区可能就由存活的消费者消费 。那存活的消费者是需要知道挂掉的消费者消费到哪了,不然怎么玩 。
这里要引出offset了,Kafka就是用offset来表示消费者的消费进度到哪了,每个消费者会都有自己的offset 。说白了offset就是表示消费者的消费进度 。
在以前版本的Kafka,这个offset是由Zookeeper来管理的,后来Kafka开发者认为Zookeeper不合适大量的删改操作,于是把offset在broker以内部topic(__consumer_offsets)的方式来保存起来 。
每次消费者消费的时候,都会提交这个offset,Kafka可以让你选择是自动提交还是手动提交 。
既然提到了Zookeeper,那就多说一句 。Zookeeper虽然在新版的Kafka中没有用作于保存客户端的offset,但是Zookeeper是Kafka一个重要的依赖 。
  • 探测broker和consumer的添加或移除 。
  • 负责维护所有partition的领导者/从属者关系(主分区和备份分区),如果主分区挂了,需要选举出备份分区作为主分区 。
  • 维护topic、partition等元配置信息
  • ….

全网最通俗易懂的Kafka入门

文章插图
这张图来源胡夕老师的《Kafka核心技术与实战》
最后通过这篇文章,文章开头那几个问题估计多多少少都懂一些啦 。我来简要回答一下:
使用消息队列不可能是单机的(必然是分布式or集群)
Kafka天然是分布式的,往一个topic丢数据,实际上就是往多个broker的partition存储数据
数据写到消息队列,可能会存在数据丢失问题,数据在消息队列需要持久化(磁盘?数据库?Redis?分布式文件系统?)


推荐阅读