1.简介
kafka是一个基于发布-订阅模式的分布式消息队列。
2.特点
2.1负载均衡
基于zookeeper的协调机制。
2.2顺序保证
Kafka保证一个Partition内的消息的有序性。
2.3冗余/可靠性
消息队列把数据进行持久化到磁盘,直到它们已经被完全处理,并且支持数据备份防止数据丢失。
2.4容错
允许集群中节点宕机(若副本数量为n,则允许n-1个节点失败)。
3.与其他消息队列的区别
从吞吐量和时延角度:
对于这四种消息队列的单机吞吐量和时延都完全可以满足我们的需求。虽然随着业务增长,topic的数据增多,集群负载增大,kafka性能会下降。但是我们的topic不会超过10个,所以不存在此问题。
从消息可靠性角度:
Bro作为消息生产者,会将流量数据打包成会话流的形式(保证报文序列的有序性),所以不用担心消息的有序性(不用保证会话流之间的有序性);所以从消息可靠性角度来看,四种消息队列都符合要求。
从高可用角度:
ActiveMQ与RabbitMQ都采用主从模式,从可用性上来说不如RocketMQ与Kafka:ActiveMQ与RabbitMQ只有主从互备的HA,负载均衡做的不好,没有消息分片;
而rocketMQ不具备选举,Master/Slave的角色也是固定的。当一个Master挂了之后,你可以写到其他Master上,但不能让一个Slave切换成Master。虽然rocketMQ也可以实现高可用,但是维护成本高,不利于小团队的开发。kafka具备选举功能,所以kafka某个partition的master挂了,该partition对应的某个slave会升级为主对外提供服务。
| 可用性 | 单机吞吐量/s | 时延 | 消息可靠性 | 消息持久化 |
ActiveMQ | 主从模式 | 万级 | ms级 |
|
|
RabbitMQ | 主从模式 | 万级 | 微秒级 | 有较低的概率丢失数据 | 1.消费端为推模型,消费状态和订阅关系由服务端负责维护,消息消费完后立即删除,不保留历史消息; 2.既支持内存队列也支持持久化队列 |
RocketMQ | 分布式 | 十万级 | ms级 | 优化后消息可以做到0丢失 |
|
Kafka | 分布式 | 十万级 | ms级 | 优化后消息可以做到0丢失,但是可能重复消费 | 只支持消息持久化,消费端为拉模型,消费状态和订阅关系由客户端端负责维护,消息消费完后不会立即删除,会保留历史消息。 |
4.架构
从宏观角度说,生产者通过网络发送消息到Kafka集群,Kafka集群将这些消息提供给消费者。
Kafka 集群的节点称为Broker,多个broker连接到相同的ZooKeeper就组成了Kafka集群。ZooKeeper主要用来实现Broker的负载均衡和容错。
一个Broker上可以创建一个或者多个Topic。同一个Topic可以在同一集群下的多个Broker中分布。
Kafka会为每个Topic维护了多个分区(partition)。每个分区是一个有序的,不可变的消息序列,新的消息不断追加到这个有组织的有保证的日志上。分区会给每个消息记录分配一个顺序ID号 – 偏移量, 能够唯一地标识该分区中的每个记录。
5.Kafka负载均衡
5.1生产者负载均衡
为了更好的做负载均衡,Kafka尽量将所有的Partition均匀分配到整个集群上。
Kafka分配Replica的算法如下:
- 将所有存活的N个Brokers和待分配的Partition排序
- 将第i个Partition分配到第(i mod n)个Broker上,这个Partition的第一个Replica存在于这个分配的Broker上,并且会作为partition的优先副本
- 将第i个Partition的第j个Replica分配到第((i + j) mod n)个Broker上
如果真按照这种算法,会存在以下明显几个问题:
- 所有主题的第一个分区都是存放在第一个Broker上,这样会造成第一个Broker上的分区总数多于其他的Broker,这样就失去了负载均衡的目的;
- 如果主题的分区数多于Broker的个数,多于的分区都是倾向于将分区发放置在前几个Broker上,同样导致负载不均衡。
解决办法:
- 分区数不能大于 Broker 的个数;
- 第一个分区(编号为0)的第一个分区放置位置是随机产生的;
- 其他分区的第一个分区放置位置相对于第0个分区依次往后移。
- 剩余的分区相对于第一个分区放置位置是随机产生的;
https://www.iteblog.com/archives/2219.html
5.2消费者负载均衡
rebalance(消费者负载均衡)的触发条件有三种:
- 组成员发生变更(新consumer加入组、已有consumer主动离开组或已有consumer崩溃了)
- 订阅主题数发生变更
- 订阅主题的分区数发生变更
Kafka新版本consumer默认分配策略:range。
对于每个主题,我们以数字顺序排列可用分区,以字典顺序排列消费者。然后,将分区数量除以消费者总数,以确定分配给每个消费者的分区数量。如果没有平均划分(PS:除不尽),那么最初的几个消费者将有一个额外的分区。
谁来执行rebalance和consumer group管理?
以前是zookeeper,性能差,不容错,故改为coordinator。
如何确定coordinator?
- 确定consumer group位移信息写入consumers_offsets的哪个分区。具体计算公式: consumers_offsets partition = Math.abs(groupId.hashCode() % groupMetadataTopicPartitionCount) 注意:groupMetadataTopicPartitionCount由offsets.topic.num.partitions指定,默认是50个分区。
- 该分区leader所在的broker就是被选定的coordinator