一、kafka的基础知识
1、基本角色
1、Producer:生产者,往broker写消息(其实是往某个topic的leader partition写消息)
2、Consumer:消费者,订阅Topic,从broker消费消息(其实是从某个topic的leader partition读消息)
3、Broker:kafka的节点(kafka的服务节点)
4、Controller:也是Broker,只不过他是Broker的主节点,
负责监听zk上原数据目录的变化,并同步到自己的内存,进而同步给集群的其他的follower节点(其他的broker节点)
5、Follower:kafka服务的从节点
负责跟Controller保持同步,同步消息和原数据,同时也会监听zk目录的变化,当controller节点宕机的时候,随时准备成为Controller节点
6、Topic:主题;类似数据库的表
7、Partition:分区;一个topic可以有多个分区
解决2个问题:1、负载均衡问题 2、大文件存储问题(把数据分布到多个partition,平均每个分区文件就变小了),这也是一种思想,我们设计分布式系统的时候都可以参考
8、Message:消息;消息存在分区里
9、offset:偏移量;消息存储进度或者消费者消费进度
10、Replica:副本;为了保证数据安全,每个partition可以设置多个副本,而多个副本中,有一个是leader replica,其他的是follower replica,leader replica其实就是leader partition(也就是对外提供读写服务的哪个分区)
2、kafka的partition
leader partition和follower partition的区别
a:生产者生产数据的时候,只会把数据写到leader partition,然后再由leader partition同步到follower partition
b:消费者消费数据也只会往leader partition 读数据
3、kafka的一些思考
3.1、follower存在的意义是什么?
当leader partition挂掉的时候(比如,leader partition所在的机器宕机了),其他的follower副本可以迅速转正,成为leader,对外提供服务,保证高可用.
3.2、follower partition怎么转正的?(leader副本挂掉后,如何选举新副本?)
如果你对zookeeper选举机制有所了解,就知道zookeeper每次leader节点挂掉时,都会通过内置id(zxid-->zookeeper transaction id),来选举处理了最新事务的那个follower节点。
从结果上来说,kafka分区副本的选举也是类似的,都是选择最新的那个follower副本,但它是通过一个In-sync(ISR)副本集合实现。kafka会将与leader副本保持同步的副本放到ISR副本集合中。当然,leader副本是一直存在于ISR副本集合中的,在某些特殊情况下,ISR副本中甚至只有leader一个副本。
当leader挂掉时,kakfa通过zookeeper感知到这一情况,在ISR副本中选取新的副本成为leader,对外提供服务。
但这样还有一个问题,前面提到过,有可能ISR副本集合中,只有leader,当leader副本挂掉后,ISR集合就为空,这时候怎么办呢?这时候如果设置unclean.leader.election.enable参数为true,那么kafka会在非同步,也就是不在ISR副本集合中的副本中,选取出副本成为leader,但这样意味这消息会丢失,这又是可用性和一致性的一个取舍了。
3.3、ISR副本集合保存的副本的条件是什么?
上面一直说ISR副本集合中的副本就是和leader副本是同步的,那这个同步的标准又是什么呢?
答案其实跟一个参数有关:replica.lag.time.max.ms。
前面说到follower副本的任务,就是从leader副本拉取消息,如果持续拉取速度慢于leader副本写入速度,慢于时间超过replica.lag.time.max.ms后,它就变成“非同步”副本,就会被踢出ISR副本集合中。但后面如何follower副本的速度慢慢提上来,那就又可能会重新加入ISR副本集合中了。
3.4、读写都是leader partition 压力不大么?
所以如果我们把leader partition集中在一台broker上,那么这台broker的压力就会很大,所以我们为了保证负载均衡,要尽量保证leader partition均匀分布
3.5、为什么follower partition不对外提供服务?
这个问题本质上是对性能和一致性的取舍。试想一下,如果follower副本也对外提供服务那会怎么样呢?首先,性能是肯定会有所提升的。但同时,会出现一系列问题。类似数据库事务中的幻读,脏读。
比如你现在写入一条数据到kafka主题a,消费者b从主题a消费数据,却发现消费不到,因为消费者b去读取的那个分区副本中,最新消息还没写入。而这个时候,另一个消费者c却可以消费到最新那条数据,因为它消费了leader副本。为了提高那么些性能而导致出现数据不一致问题,那显然是不值得的
3.6、ack机制
跟副本关系最大的,是acks机制,acks决定了生产者如何在性能与数据可靠之间做取舍。
acks这个配置可以指定三个值,分别是0,1和-1。他们分别代表:
0:这意味着producer发送数据后,不会等待broker确认,直接发送下一条数据,性能最快
1:为1意味着producer发送数据后,需要等待leader副本确认接收后,才会发送下一条数据,性能中等
-1:这个代表的是all,意味着发送的消息写入所有的ISR集合中的副本(注意不是全部副本)后,才会发送下一条数据,性能最慢,但可靠性最强
还有一点值得一提,kafka有一个配置参数,min.insync.replicas,默认是1(也就是只有leader,实际生产应该调高),该属性规定了最小的ISR数。这意味着当acks为-1(即all)的时候,这个参数规定了必须写入的ISR集中的副本数,如果没达到,那么producer会产生异常。
4、kafka架构的思考
4、1 kafka是一个把性能用到极致的框架,是一个支持高并发,高性能,高可用的分布式消息系统,假日是你,你怎么设计他的服务端呢?你会从哪些角度去提升呢?
网络
磁盘
CPU
内存
4、2 服务端设计:服务端请求是如何处理的?
NIO
参考文档: