1. Kafka和ZK的关系
-
元数据存放到zk(节点中),应用了zk统一命名的功能
- 集群节点信息:brokerId 每台机器的id
- topic信息:在哪台机器上的哪个位置
- parition主从信息:每个partition多个副本中,谁是老大
-
partition_0 有多个副本,需要选择出老大,应用了zk的分布式锁功能
-
Kafka没有单独的界面,观察zk节点或者安装Kafka-eagle
Kafka-eagle安装及简介
访问端口:http://node03:8048/ke 注:kafka-eagle安装在第三台机器上 -
Zookeeper上的细节:
1.每个 broker 启动后会在 zookeeper 上注册一个临时的 broker registry,包含 broker 的 ip 地址和端口号,所存储的 topics 和 partitions 信息。2.每个 consumer 启动后会在 zookeeper 上注册一个临时的 consumer registry:包含 consumer 所属的consumer group 以及订阅
2. Kafka简介
2.1 版本
- Kafka是使用scala编写的,依赖scala的版本,Kafka版本由kafka&scala组成,如下表示使用scala2.11版本编写的kafka2.11版本
- 服务器的版本和客户端的版本要相同,否则无法连接到服务器
2.2 集群架构
Kafka Cluster:天生的分布式消息存储,每一台机器是一个broker,每一台机器有brokerId,存储在ZK中。
Kafka Cluster:由多个服务器组成,每个服务器单独的名字broker(掮客)
Kafka Producer:生产者、负责生产数据。
Kafka Consumer:消费者、负责消费数据。
Kafka Topic:主题,一类消息的名称。存储数据时将一类数据存放到某个topic下,消费数据也是消费一类数据。
比如:
3. Kafka 原理
3.1 分片&副本原理
- 消息太多,一台机器存不下了,需要分成多个部分分散到多台机器上。
- 为了防止数据丢失,需要给每一个分片设置备份
3.2 消息存储&查找机制
- 每个分区会对应一个文件夹
比如/export/data/kafka/order_0文件夹就是order主题的第一个分区。 - 每一个文件夹中会有多个sagment段(每个sagment段默认1G),sagment包括xxx.index和xxx.log
- xxx.index记录每条消息在xxx.log中的位置(offset),第一个sagment的xxx.index为0000.index(起始偏移量为0)
- xxx.log是真正存放数据的文件
- 一个sagement大约1G
- 查找时
- 会根据记录的offset二分查找,找到对应的xxx.index
- 根据xxx.index中记录的顺序查找得到对应的消息‘
3.3 生产者分发策略
Kafka在数据生产的时候,有一个数据分发策略。默认的情况使用DefaultParitioner.class类。这个类中就定义数据分发策略。
- 如果是用户指定了parition,生产就不会调用DefaultParitioner.parition()方法。数据就会发送到指定的partition上
- 当用户指定key,使用hash算法。如果key一直不变,同一个key算出来的hash值是个固定值,这种hash取模就没有意义。
Utils.toPositive(Utils.murmur2(keyBytes)) % numParitions
- 当用户既没有指定paritiion也没有指定key,消息随机分配
3.4 消费者 消费时负载均衡
3.4.1 原理
- 消费同一个主题中的一个分区,同一时间只能被同一个消费者组的同一个消费者消费,只能消费后会把offset记得到zk或者kafka文件中。
- 一个消费者不可能消费多个分区的消息
- 一个分区的消息也不可能被同一个组的多个消费者消费
- 最好的状态是1:1
3.4.2 问题
- 生产者的生产速度很快,消费者跟不上,造成数据量大量滞后和延时,怎么办?
- 多几个消费者,共同来消费数据
- 新的问题,消费组中消费者的数量和partition数据一致,但是消费者的处理速度还是跟不上,怎么办?
- 错误解决方案:再加一个消费者,由负载均衡规定,多出来的消费者会处于空闲状态
- 正确解决方案:要么修改topic的patition的数量,要么减少消费者处理时间,提高处理速度。
4. Kafka消息不丢失原理
4.1 生产者消息不丢失
- ack反馈机制, 0 ,1,-1三个信号
- 0 生产者生产消息,topic没有接收到消息
- 1 生产者生产消息,存放消息的topic分区,分区老大接收到了消息
- -1 生产者生产消息,存放消息的topic分区,分区老大和其他副本都接收到了消息
- 面试问题
- 如果broker一直不给ack,怎么办?
–>设定超时时间,超过规定时间就默认发送失败,重新发送 - broker一条一条反馈(同步发送),浪费带宽,怎么解决?==>异步发送
生产者将消息放到缓存池中,缓存池积累到比如500条时,集中写到服务器中,
这时候topic的所有副本都接收到消息,broker反馈-1,缓存池再写下一条。 - 如果缓存池满了,但是broker一直不给ack,怎么办?
定期定量清理缓存池,消息重新发
- 如果broker一直不给ack,怎么办?
4.2 存储者
topic 分区&副本机制
4.3 消费者
- 消费者 消费完消息会将分区文件夹中sagment 里面的offset(xxx.index)记录下来,比方_consumer_offsets_25
- 一部分数据会存放到zk中
- 一部分数据会存放到同一个分区文件夹中
- 问题(offset存放到zk中,会有重复消费的问题发生)
- 消费完,没来得及记录,突然断电了
- 这种情况,下次重新启动集群就会造成重复消费
如果喜欢本文章,请用小手点个赞~