kafka这几年在分布式领域的用途也是非常火热 , 感觉有超越老牌rabbitMQ的趋势。在大数据的时代,数据对我们也是越来越重要,就拿web系统来说,现在系统都走向了微服务,分布式,随之而来的是大量的日志信息,这些日志信息,收集起来也是一个问题,对于rabbitMQ来说,这些日志信息太多了,全交给它来说,越来太大。于是kafka就成了新的代言者,kafka刚好也有发布订阅等消息中间件特性。
kafka消息模型如下
图中的broker可能有点瑕疵,在kafka中叫做topic。
一个topic可以理解为一个容器,这种模式中也有发布和订阅模式,即生产者将消息发布到topic中,然后消费者订阅此topic进行消息的消费。
对于任何一个MQ来说吞吐量都是一个特别重要的标准,kafka之所以吞吐量如此高是因为,它发送消息的时候使用的批处理,不是一条一条的发送(rabbitMQ是一条一条发送的),而是一小批,一小批的,发送。它在缓冲一段时间后,一下把缓存的消息都发送,这样和broker的交互就相对的少了,速度自然就快了。
还有一个重要的一点是kafka每次写入的时候都会把消息写入到页缓存中,而页缓存是在内存中分配的,所以速度也是非常的快。
kafka写入的时候是直接在文件使用append的方式,又比随机写磁盘要快。
kafka整体架构
生产者----------------------------------kafka集群--------------------消费者
zookeeper集群(kafka集群依赖于zookeeper集群
这就是kafka(集群的时候使用的主从复制模式,主节点负责读写,主节点挂掉了,可以通过内部的isr机制来进行选举,选出新的leader)的整体架构
生产者发送消息到topic中某个partition中,然后消费者订阅topic中的某个partition来实现消费
图中涉及到概念有:
producer: 消息的发送者用来发送消息到topic中的某个分区
Consumer :消息消费者,向kafka broker取消息的客户
Topic :可以理解为一个队列;
Consumer Group: 消费者组,表示多个消费者组成的集合,一个topic可以有多个消费者组,理论上一个消费者组中的消费者可以共享同一个topic,但是真正消费的时候,同一个消费者组下的消费者不能消费同一分区,因为这样可能会导致offset错乱
Broker :一台kafka服务器就是一个broker。一个集群由多个broker组成。一个broker可以容纳多个topic;
Partition:为了实现扩展性,一个非常大的topic可以分布到多个broker(即服务器)上,一个topic可以分为多个partition,每个partition是一个有序的队列。partition中的每条消息都会被分配一个有序的id(offset)。kafka只保证按一个partition中的顺序将消息发给consumer,不保证一个topic的整体(多个partition间)的顺序.
offset:偏移量,存在于partition中,作用是记录kafka的消费位置,kafka不像rabbitMQ,每消费一条消息就删除一条,它是消费之后在偏移量中记录消费的位置,下次消费的时候从上次记录的位置开始算起。
图中的partition和offset都是有序的
,生产的消息被不断追加到Partition log上,其中的每一个消息都被赋予了一个唯一的offset值。
分区的原因
(1)方便在集群中扩展,每个Partition可以通过调整以适应它所在的机器,而一个topic又可以有多个Partition组成,因此整个集群就可以适应任意大小的数据了;
(2)可以提高并发,因为可以以Partition为单位读写了。这样就不会说一个topic中的消息太多,而炸掉
分区原则
(1)指定了patition,则直接使用;
(2)未指定patition但指定key,通过对key的value进行hash出一个patition;
(3)patition和key都未指定,使用轮询选出一个patition。
副本(Replication)
同一个partition可能会有多个replication(对应 server.properties 配置中的 default.replication.factor=N)。没有replication的情况下,一旦broker 宕机,其上所有 patition 的数据都不可被消费,同时producer也不能再将数据存于其上的patition。引入replication之后,同一个partition可能会有多个replication,而这时需要在这些replication之间选出一个leader,producer和consumer只与这个leader交互,其它replication作为follower从leader 中复制数据。
集群:
在开始kafka集群之前必须先搞一搞zookeeper的集群,zk集群的核心是myid文件(无后缀)
zk集群之后配置下列信息
配置文件在config/server.properties
broker.id=0,
listeners =PLAINTEXT://ip:port
zookeeper.connect=zk1:port,zk2:port,zk3:port
delete.topic.enable 是否允许kafka集群删除t局opic及其数据
log.retention.{hours|minutes|ms} 控制消息数据的留存时间,时,分,秒 ,默认留存时间是7天
log.retention.bytes 设置kafka集群为每个消息日志保存多大的数据,如果数据超过了kafka会启动清理策略
默认值为-1,表示不会根据日志文件的总大小来删除日志
num.network.threads 控制了broker在后台处理请求的线程数,默认是3
num.io.threads 实际处理网络请求的线程数,默认值是8
message.max.bytes kafkabroker 能接受最大消息大小,默认是997kb,实际中需要修改
其它配置文件只需要改id的值和监听的端口号就可以加入集群了,加入 kafka内部就会在新节点复制信息,这样就达到轻量级的动态扩展.
kafka消息的写入流程
1)producer先从zookeeper的 "/brokers/.../state"节点找到该partition的leader
2)producer将消息发送给该leader
3)leader将消息写入本地log
4)followers从leader pull消息,写入本地log后向leader发送ACK
5)leader收到所有ISR中的replication的ACK后,增加HW(high watermark,最后commit 的offset)并向producer发送ACK
broker 存储消息的方式
1.物理上把topic分成一个或多个partition(对应server.properties中的num.partition=3配置)每个对应的partition物理上对应一个文件夹,(该文件夹存储此分区的所有消息和索引记录文件)
存储策略
这个在上面的配置文件中已经有所说明
在对应的broker中设置这些信息,即可。
zookeeper存储结构
注意:producer不在zk中注册,消费者在zk中注册。
1.图中可以看到消费者会将自己的信息在zookeeper中的注册,包括自己所在的消费者组,自己的组id,偏移量(offset)和主题信息(topic).
2.其它信息都是broker依赖于消费者的集群,选举等信息,看下即可
重提消费者组
消费者一般是以consumer group消费者组的方式工作,由一个或者多个消费者组成一个组,共同消费一个topic。每个分区在同一时间只能由group中的一个消费者读取,但是多个group可以同时消费这个partition。
好处在于 消费者可以通过水平扩展的方式同时读取大量的消息。如果一个消费者失败了,那么其他的group成员会自动负载均衡读取之前失败的消费者读取的分区(这一点就比较流弊)
消费方式
consumer采用pull(拉)模式从broker中读取数据。
push(推)模式很难适应消费速率不同的消费者,因为消息发送速率是由broker决定的。它的目标是尽可能以最快速度传递消息,但是这样很容易造成consumer来不及处理消息,典型的表现就是拒绝服务以及网络拥塞。(rabbitMQ是使用推的方式,因为rabbitMQ中的消息远没有kafka的消息频率那么大(kakfa在大数据方向,应用广泛),并且在rabbit中如果消息太多阻塞了,可以用动态生成多个消费者协助消费来度过阻塞期)
pull模式也是有缺点的,当broker中没有消息的时候,消费者会陷入自己的循环中,白白消耗性能。这个时候就需要对consumer进行阻塞操作。
上图为观察者模型图,其实MQ的底层就是基于观察者机制来实现,如果能看懂jdk的观察者机制,就可以自动MQ的设计理论了
图中的具体主题就可以理解为一个kafka中的topic或者分区。可以理解为一个集合,然后具体的观察者可以理解为消费者原型。
消费者订阅集体的topic后,将此消费者的加入到具体的topic集合中,然后当次topic集合有消息的时候就会将消息发送给集合里面的所有成员,这样就形成了一个简单的发布订阅机制。jdk底层的观察者机制也确实是这么干的,spring底层的监听机制就是以此为思想进行实现的。由此可见设计模式之强大哈哈。
本篇文章写到这吧,后面会在介绍,broker,producer,consumer,设计原理。
以及kafka集群调优,监控和管理。
-------------------------------本文知识储备来自于蚂蚁课堂,感谢余总的指点。