柚子快报邀请码778899分享:分布式 【中间件】kafka

http://www.51969.com/

目录

一、概述二、生产者1. 发送原理2. 生产者分区 Partition分区好处分区策略

3. 生产者如何提高吞吐量4. 数据可靠性ACK应答级别数据不丢失:ACK + ISR数据不重复:幂等性数据有序

三、broker1. 工作流程2. 副本相关3. 底层存储4. 高效读写数据

四、消费者1. 工作流程2. 分区分配和重平衡3. offset 位移

一、概述

定义:是一个分布式的基于发布/订阅模式的消息队列(MessageQueue),主要应用于大数据实时处理领域 三大功能

削峰: 高峰期的消息可以积压到消息队列中,随后平滑地处理完成,避免突发访问压力压垮系统解耦: 消息队列避免模块之间的相互调用,降低各个模块的耦合性,提高系统的可扩展性异步: 发送方把消息放在消息队列中,接收方无需立即处理,可以等待合适的时间处理 基础架构:

组件作用Producer消息生产者,就是向 Kafka broker 发消息的客户端Consumer消息消费者,向 Kafka broker 取消息的客户端Consumer Group(CG)消费者组,由多个 consumer 组成。组内每个消费者负责消费不同分区的数据,一个分区只能由一个组内消费者消费;消费者组之间互不影响。消费者组是逻辑上的一个订阅者Broker一台 Kafka 服务器就是一个 broker。一个集群由多个 broker 组成。一个broker 可以容纳多个 topicTopic消息主题(逻辑概念) ,生产者和消费者面向的都是一个 topicPartition一个 topic 可以分为多个 partition,每个 partition 是一个有序的队列Replica副本。每个分区都有若干个副本,一个 Leader 和若干个FollowerLeader一组副本中的“主”,只有主和生产者消费者交互Follower一组副本中的“从”,实时从 Leader 中同步数据,保持和Leader 数据的同步SegmentPartition 物理上被分成多个 Segment,每个 Segment 1个GZookeeper保存元信息,现已废除

二、生产者

1. 发送原理

涉及到了两个线程——main 线程和 Sender 线程

在 main 线程中创建了一个双端队列 RecordAccumulator。main 线程将消息发送给消息队列当消息队列内的消息达到一定大小,或者达到时间限制,会通知sender线程Sender 线程不断从消息队列中拉取消息发送到 Kafka Broker

可以选择是异步还是同步(同步就是sender等待收到broker的ack后,再去发送新消息)

2. 生产者分区 Partition

分区好处

便于合理使用存储资源,可以把海量的数据按照分区切割成一块一块数据存储在多台Broker上。合理控制分区的任务,可以实现负载均衡的效果提高并行度,生产者可以以分区为单位发送数据;消费者可以以分区为单位进行消费数据

分区策略

生产者生产消息的时候:

指明partition的情况下,直接将指明的值作为partition值;例如partition=0,所有数据写入分区0 没有指明partition值但有key的情况下,将key的hash值与topic的partition数进行取余得到partition值 例如:key1的hash值=5, key2的hash值=6 ,topic的partition数=2,那么key1 对应的value1写入1号分区,key2对应的value2写入0号分区 既没有partition值又没有key值的情况下,Kafka采用Sticky Partition(黏性分区器),会随机选择一个分区,并尽可能一直使用该分区,待该分区的batch已满或者已完成,Kafka再随机一个分区进行使用(和上一次的分区不同)。 例如:第一次随机选择0号分区,等0号分区当前批次满了(默认16k)或者linger.ms设置的时间到, Kafka再随机一个分区进行使用(如果还是0会继续随机) 自定义分区:定义类实现 Partitioner 接口,重写 partition()方法,方法返回分区号

3. 生产者如何提高吞吐量

提高main线程创建的消息队列大小:缓存大一点提高batchsize大小:多等一些数据再传调整等待时间:双刃剑,太短一次传的消息太少,太长有延迟对传输数据做压缩:能传更多的消息

4. 数据可靠性

ACK应答级别

0:生产者发送过来的数据,不需要等数据落盘应答 1:生产者发送过来的数据,Leader收到数据后应答 -1:生产者发送过来的数据,Leader和ISR队列里面的所有节点收齐数据后应答

单纯用0或1都会导致丢数,而单纯用-1会导致多数重复

数据不丢失:ACK + ISR

ACK = -1 + 副本 >= 2 + ISR最小副本数量 >= 2

数据不重复:幂等性

数据语义

最多一次:ACK = 0至少一次:ACK = -1 + 副本 >= 2 + ISR最小副本数量 >= 2精确一次:幂等性 + 至少一次 重复数据的判断标准:具有 相同主键的消息提交时,Broker只会持久化一条

PID是Kafka每次重启都会分配一个新的Producer IDPartition 表示分区号Sequence Number是单调自增的 所以幂等性只能保证的是在单分区单会话内不重复 全局不重复需要开启事务

数据有序

生产者有序发送消息

一个一个消息的发:一个 Topic 下的同一个 Partition 一定是有序的不是一个一个发:需要开启幂等性且一次发不能超过5个,这样如果乱序到达的话,broker会自己排序 消费者有序消费

一个分区只让一个消费者来消费,即能保证

三、broker

1. 工作流程

生产者将消息发送给分区 LeaderLeader 将消息写入本地文件对应的 Follower 从 Leader 拉取消息并写入本地文件Follower 向 Leader 发送 ACKLeader向生产者回复

leader的维护由保存在paitition内的Controller来做,Controller也是分布式的,他会监听brokers节点的变化,在节点挂掉的时候辅助选举新leader,选举规则:在ids列表内按顺序选择

2. 副本相关

定义:每个partition都有多份,叫副本,来提高可靠性

副本分为Leader和Follower,只有Leader和生产者和消费者交互副本AR = ISR + OSR Leader 和 Follower 故障处理

Follower故障:被踢出ISR,恢复后再加入ISRLeader故障:从ISR中选出一个新的Leader,恢复后去除旧数据,和新Leader进行同步(只能保证副本之间的数据一致性,并不能保证数据不丢失或者不重复) 副本分区分配 尽可能的把Leader散开,否则会对某一个broker产生很大的压力

3. 底层存储

partition下进一步将数据分为Segment,每个1G

Segment分为

log:存具体数据,以追加的方式index:索引,稀疏索引,4KB记一条索引时间戳:过期删除用的 删除方法

删除:直接删除压缩:相同key只保留最新的

4. 高效读写数据

Kafka 本身是分布式集群,可以采用分区技术,并行度高读数据采用稀疏索引,可以快速定位要消费的数据顺序写磁盘页缓存 + 零拷贝技术

页缓存PageCache:重度依赖底层操作系统提供的PageCache功能,写的时候直接交给页缓存,读的时候先读页缓存,没有再读磁盘零拷贝:消息从磁盘里读出来之后不走应用层代码,直接走网卡,不占用CPU

四、消费者

1. 工作流程

消费者可以分组,一个分区只能由组内的一个消费者消费,消费者组是逻辑上的一个订阅者用offset标识消费的位置,由消费者提交,保存在主题内,由coordinator管理,这也是个分布式

主要就是从broker里拉取数据

2. 分区分配和重平衡

分区分配问题:一个consumer group中有多个consumer组成,一个 topic有多个partition组成,问题是,到底由哪个consumer来消费哪个partition的数据

分区分配策略

Range:对每个 topic 而言, partitions数/consumer数来决定,会产生数据倾斜RoundRobin:针对集群中所有Topic而言,所有的 partition轮询分配Sticky:尽量均匀地分配分区,根据上次的分配结果尽量减少变动

3. offset 位移

位移保存方式:存在__consumer_offsets里,采用 key 和 value 的方式存储数据。key 是 group.id+topic+分区号,value 就是当前 offset 的值 位移的提交方式

自动提交(可能造成重复消费) 重复消费:已经消费了数据,但是 offset 没提交 比如每隔5s,下一轮过了2s挂了,会重复消费这2s的内容 手动提交(可能造成漏消费) 漏消费:先提交 offset 后消费,有可能会造成数据的漏消费 比如消费者取了,还在内存里,刚提交还没来得及落盘就挂了,没落盘的就漏消费了 不管是重复消费还是漏消费,都是提交和落盘的间隙出现宕机的情况,可以开启事务,把这两个动作原子绑定

柚子快报邀请码778899分享:分布式 【中间件】kafka

http://www.51969.com/

查看原文