Kafka学习总结
1、卡夫卡的定义
(1)传统
卡夫卡是一个分布式的基于发布订阅模式的消息队列,主要应用于大数据实时处理
【发布 / 订阅】
消息的发布者不会将消息直接发送给特定的订阅者,而是将发布的消息分为不同的类别,订阅者只接受感兴趣的消息
(2)最新
卡夫卡是一个开源的分布式事件流平台,被千家公司用于高性能数据管道、流分析、数据集成和关键任务应用
2、消息队列
常见的消息队列有 Kafka、ActiveMQ、RabbitMQ、RocketMQ 等
大数据常用卡夫卡,javaEE 常用 AcitveMQ、RabbitMQ、RocketMQ
(1)传统消息队列应用场景
缓存 / 消峰、解耦、异步通信
【1】缓存 / 消峰
【2】解耦
【3】异步通信
3、消息队列的两种模式
(1)点对点模式
消费者主动拉取数据,消息收到后删除消息
(2)发布 / 订阅模式
可以有多个 topic 主题 (浏览、点赞、收藏、评论)
消费者消费数据后不删除数据
每个消费者相互独立,都可以消费到数据
(3)不同之处
【1】点对点只有一个主题,发布订阅有多个主题
【2】点对点消费完删除,发布订阅不会
【3】点对点只有一个消费者,发布订阅可以有多个消费者
4、基础架构
(1)为方便扩展,并提高吞吐量,一个 topic 分为多个 partition
(2)配合分区的设计,提出消费者组的概念,组内每个消费者并行消费,一个分区的数据只能由一个消费者进行消费
(3)为提高可用性,每个 partition 增加若干副本,类似与 namenode HA
(4)ZK 中会记录谁是 leader,kafka2.8.0 后配置不采用 ZK
5、server.properties 参数设置
broker.id=0 #每个节点参数唯一, 分发后要修改
log.dirs=/opt/module/kafka/datas #运行日志存储
zookeeper.connect=hadoop102:2181,hadoop103:2181,hadoop104:2181/kafka #为了便于在 zookeeper 中管理 kafka 的地址所以在 zk 根目录下创建了 kafka
6、kafka 关闭注意事项
注意:停止 Kafka 集群时,一定要等 Kafka 所有节点进程全部停止后再停止 Zookeeper 集群。因为 Zookeeper 集群当中记录着 Kafka 集群相关信息,Zookeeper 集群一旦先停止,Kafka 集群就没有办法再获取停止进程的信息,只能手动杀死 Kafka 进程了。
7、topic 命令
注意:分区的修改只能增加不能减少
8、生产者原理
附注:
(1)一个分区会创建一个队列
(2)内存总大小 32M, 一个批次大小 16k
(3)只有数据积累到一个批次大小后才会发送 (16k)
(4)如果数据迟迟没有达到一个批次大小,sender 等待设定的时间后就会发送数据,linger.ms 单位 ms, 默认为 0, 表示没有延迟
(5)在发送的请求 request 没有收到应答时可以继续发送,但是最多发送 5 个,超过 5 个就会停止发送
(6)应答级别 acks
【1】0:生产者发过来的数据,不需要等数据落盘应答
【2】1:生产者发送过来的数据,leader 收到数据后应答
【3】-1:(all) 生产者发送过来的数据,leader 和 ISR 队列里面的所有节点收齐数据后应答,-1 和 all 等价
(7)selector 负责打通数据传输的输入流和输出流
(8)若应答成功,需要清除内存池里的数据和发送序列里的请求
(9)失败重试的次数默认 int 的最大值,不断直到成功为止
9、异步发送
这么做能够解决大量用户需要请求发送短信的情况,通过将短信发送和返回确认分开的方式做到了既能稳定发送短信,还能及时回复确认信息
10、待回调函数的异步发送流程
回调函数会在 producer 收到 ack 时调用,为异步调用,该方法有两个参数,分别是元数据信息(RecordMetadata)和异常信息(Exception),如果 Exception 为 null,说明消息发送成功,如果 Exception 不为 null,说明消息发送失败。
能够返回主题、分区等信息
11、同步发送(同时把所有数据发完才继续)
同步发送要求在内存池中的数据必须一批全部发送完毕才能发送下一批,一批批地发送
12、生产者分区
(1)分区的好处
【1】便于合理利用存储资源,每个 Partition 在一个 broker 上存储,可以把海量数据按照分区切割成一块一块的数据存储在多个 Broker 上,合理控制分区的任务,可以实现均衡负载的效果
【2】提高并行度,生产者可以分区为单位发送数据,消费者可以分区为单位进行消费数据
(2)分区策略
(3)自定义分区器
【1】定义类实现 Partitioner 接口。
【2】重写 partition() 方法。
(4)生产者如何提高吞吐量
【1】在低延迟的前提下尽量扩大批次大小
batch.size: 批次大小,默认 16k -> 32k
linger.ms: 等待时间,修改为 5-100ms
【2】compression:压缩 snappy
压缩提高吞吐量
【3】RecordAccumulator:缓冲区大小,修改为 64m
适用于分区非常多的情况
(5)数据可靠性
ACK 应答级别
解决办法
数据完全可靠条件:
【1】应答级别为 - 1
【2】leader 要至少 2 个
【3】isr 要至少 2 个
应答级别用途
【1】acks=0 几乎没有人用,可靠性低,效率高
【2】acks=1 可靠性中等,效率中等,用于传输普通日志,允许丢个别数据
【3】acks=-1,一般用于传输和钱有关的数据,对可靠性要求较高的场景,存在数据重复的问题
(6)数据重复问题
leader 在成功发送数据,准备返回确认消息时挂掉,新的 leader 会重复发送导致数据重复
数据传递语义
解决方法:幂等性(三个参数决定是否重复)
单独的 PID 无法确认是否为同一份数据,因为 PID 会在服务重启后重新分配
幂等性默认是开启的
生产者事务(必须开启幂等性)流程
【1】producer id 的生成
【2】发送数据
【3】关键信息的持久化存储
【4】询问数据是否处理完毕,等待返回成功
【5】持久化事务成功信息
附注:事务 id 必须手动配置且唯一
(7)数据有序
希望生产者生产的数据在消费者消费时依然是有序的
单分区内有序相对易于实现,但有条件
多分区内有序可以办到,需要各个分区将数据放在一起做全排序,但是效率低下
(8) 数据乱序(重点)
若发送的 1、2、4 请求成功,但是 3 失败了,就会导致出现数据的乱序现象
开启幂等性后最多也只能保证 5 个以内的请求数据有序
13、zk 存储
工作原理
【1】broker 启动,在 zk 中进行注册
【2】选出 leader 选举的老大,谁先注册谁说的算
【3】选出的老大监听 borkers/ids/,有任何变化都能监听的到
【4】AR(kafka 分区中所有副本的统称), 只有在 isr 中活着的排在前面的优先,采用顺序轮替
【5】将 leader 信息和 isr 信息进行备份,同步信息,采用 segment 存储
【6】使用 index 索引加快查询速度
14、节点的服役和退役 (生产重要经验)
(1)服役新节点
在新节点安装 JDK、kafka 后启动即可
【1】记得修改 IP
vim /etc/sysconfig/network-scripts/ifcfg-ens33
vim /etc/hostname
【2】删除 kafka 中的 datas/ logs / 文件夹
【3】修改 server.properties 中的独一无二的 id
【4】对指定主题重新进行负载均衡
(2)退役旧节点
【1】按照前文执行负载均衡计划
【2】执行停止命令
15、kafka 副本
副本在生产环境中通常 2 个,默认 1 个
和 hadoop 副本的不同之处在于 kafka 的副本有 leader 和 follower
isr 里 leader 和 follower 之间的通讯必须在 30s(默认) 内应答,超过就会被踢出
16、Leader 选举
(1) 一个主题有多个分区
(2) 一个分区有多个副本 (replicas)
(3)replicas 中排第一的副本为该分区的 leader
(4) 当排第一的副本挂掉,就会让后续副本递上成为 leader
(5) 若挂掉的排第一的副本恢复,则在 ISR 中该副本会排到后面,但是在 replicas 中的顺序不变。若当前 leader 再次挂掉,则排第一的恢复后的副本重新成为 leader
17、follower 故障
(1)每个副本的最后一个 offset + 1 为 LEO
(2)最小的 LEO 为 HW
(3)如果一个 follower 挂了并重新恢复,会把之前 HW 以后的数据删除并从 HW 开始重新同步数据到最新的 HW 上
18、Leader 故障
19、分区副本分配
第一次不空位轮替
第二次空一位轮替
第三次空两位轮替
20、手动调整分区副本存储
21、Leader Partition 自动平衡
当某些 broker 宕机,会导致 leader partition 过于集中在其他少部分几台 broker 上,进而导致部分 broker 读写请求压力过高,部分又太低,造成负载不均衡
因此当,每个 broker 都设有一个允许的不平衡的 leader 的比率,超过这个比率值就会触发 leader 的平衡,默认 10%
自动平衡默认开启,默认 300 秒检测一次
22、增加副本因子
只能手动增加
23、kafka 文件存储机制
文件机制:topic - partititon - log - segment(1g)
索引方式:系数索引 (.log .index)
右侧大表存储 4kb 数据才会增加一条索引
24、文件清理策略
一般按照天或者分钟来设置保存时间,时间单位越小优先级越高,会覆盖低优先级设置
默认 7 天 生产环境 3 天 个别生产线调整为 7 小时
清理策略
(1)删除策略
基于时间,默认打开。以所有记录中最大的时间戳作为文件时间戳,超过期限后删除
基于大小,默认关闭。止呕超过设置日志的总大小才会删除最早的 segment
(2)压缩
只保留最新版本,适用于消息的 key 是用户 ID,value 是用户的资料,通过这种压缩策略,整个消息总集里就保存了所有用户的最新资料
25、高效读写数据
(1)分布式集群,分区技术,并行度高
(2)采用稀疏索引读取数据,可快速定位
(3)顺序写磁盘
(4)页缓存 (内核缓存)+ 零拷贝
kafka 应用层不参与存储数据的调用,所有和消费者请求数据有关的功能都会交给页缓存来做
26、Kafka 消费方式
27、消费者工作流程
offset 目前存储在系统主题中,过去是存放在 zookeeper 中,但这会增加 zookeeper 和用户的网络传输交互压力,因此进行了更改
在单个消费者进行消费时,一个分区一次只和一个消费者交互,但一个消费者可以多次和多个消费者交互
28、消费者组
(1)原理
(2)初始化
每个 broker 都会有一个 coordinator 来负责初始化。一个 group 组会根据其 groupid 哈希值 % 分区数量的结果来选择 coordinator,组员会主动向它发送加入组的请求,coordinator 会随机选择组中的一位当组长让他制定消费方案并返回。最后根据这个方案执行
一旦有一个组员掉线 (无响应、长时间处理) 就会移除该组员,并触发再平衡
心跳默认 3s 一次,超时默认 45s,消息处理时长过长阈值默认 5 分钟
(3)消费流程
达到最小字节 (默认 1 字节) 或者超时(默认 500ms)后抓取一批数据到 completedFetches 里。消费者每批次返回给消费者的数据最大条数(默认 500 条)
拦截器的作用主要是用于处理数据以及监控 kafka 集群的运行情况
29、生产经验——分区的分配以及再平衡
主流的四种方式:Range、RoundRobin、Sticky、CooperativeSticky
默认策略:Range + CooperativeSticky
(1)Range
模余得到每个消费者消费几个分区,多出来的分区也平均分配,易产生数据倾斜
如果其中一个消费者挂了会把该消费者的分区全部给其中一个活着的消费者
(2) RoundRobin
注意是对于所有 topic 的分区进行哈希编号轮循
如果有其中一个消费者挂了就回把挂了的分区轮循给剩下的消费者
(3)Sticky 以及再平衡
如果一个消费者挂了会尽可能平均给其他人
30、offset 的默认维护位置
消费者消费完了消息是不会被立刻删除的, 每个消费者把消费的数据消费到哪里了就需要做个记录, 就是 offset。
由于 consumer 在消费过程中可能会出现断电宕机等故障,consumer 恢复后,需要从故障前的位置的继续消费,所以 consumer 需要实时记录自己消费到了哪个 offset,以便故障恢复后继续消费。
在 0.9 版本之前,offset 维护在 zookeeper 中;在 0.9 版本之后,offset 维护在系统主机当中
consumer 默认将 offset 保存在 Kafka 一个内置的 topic 中,该 topic 为”__consumer_offsets”
https://lilinchao.com/archives/1546.html
31、自动 offset
默认 5s 自动提交 offset
32、手动提交 offset
同步提交阻塞当前线程一直提交到成功或者失败
异步提交没有失败重试机制,所以可能提交失败
33、指定 offset 消费
指定 offset 的目的是控制消费者在读取消息时的起始位置。通过指定 offset,消费者可以跳过一些已经处理过的消息,或者从特定的位置开始读取消息。这样可以避免重复消费或者漏消费的情况。
34、指定时间消费
怀疑某个时间段消费的数据存在问题,需要重新进行消费,这就需要用到指定时间的消费
35、漏消费和重复消费
漏消费:先提交 offset 后消费,有可能造成数据的漏消费
重复消费:先提交 offset 后消费,有可能会造成数据的漏消费
解决方法:采用消费者事务
36、生产经验——数据积压 (重点)
消费者如何提高吞吐量
(1)增加分区和消费者个数 (CPU 核数),提高并行度
(2)提高单批次拉取条数,注意不要超过每批次大小阈值 两个参数 50M 500 条
37、按照主题消费
(1)配置信息
连接
反序列化
组 ID
(2)创建消费者
(3)订阅主题
38、offset
(1)默认存储在系统主题
(2)自动提交 5s 默认
(3)手动提交 同步、异步
(4)指定 offset 消费 seek()
(5)按照时间消费
(6)漏消费 重复消费
采用事务处理且下游也需要支持事务处理
生产端 =》集群
集群 =》消费者
消费者 =》框架
39、kafka-kraft 模式
使用该模式后不再需要使用 zookeeper
40、Flume
(1)生产者
taildirsource: 支持断点续恒,时刻监控每一个数据的变化
memory channel: 完全基于内存,速度快,但容易断电后丢数据
a1.sources.r1.filegroups.f1 监控目录
a1.sources.r1.positionFile 存放 offset 目录
a1.sources.k1.kafka.flumeBatchSize 从 flume 中一批次拉取多少条数据
(2)消费者
kafka.topics.regex 优先级更高,它是正则模式
a1.sources.r1.batchDurationMills 每批次拉取时间间隔
41、springboot
42、Spark
43、kafka 硬件配置选择
(1)假设场景
(2)配置
【1】 100 万日活 * 每人每天产生日志 100 条 = 1 亿条(中型公司)
处理日志速度 1 亿条 / (24*3600s) = 1150 条 / s
1 条日志 (0.5k - 2k 1k )
1150 条 * 1k /s= 1m/s
高峰值 (中午小高峰 8-12 点) * 20 倍 = 20m/s - 40m/s
【2】购买多少台服务器
服务器台数 = 2 * (生产者峰值生产速率 * 副本数 / 100 ) + 1
=2 * (20m/s * /100) + 1
=3 台
【3】磁盘选择
kafka 按照顺序读写 机械硬盘和固态硬盘顺序读写速度差不多
1 亿条 * 1k = 100g
100g * 2 个副本 * 3 天 / 0.7 = 1T
建议三台服务器总的磁盘大小 大于 1T
【4】内存选择
kafka 内存 = 堆内存 (kafka 内部配置) + 页缓存 (服务器内存)
(a) 堆内存 10-15g
(b) 页缓存 segment (1g) (分区数 Leader(10) * 1g * 25%) / 3
= 1g
一台服务器 10g + 1g
【5】*****
24(12+4+8) + 8(其他线程)= 32
【6】网络选择
网络带宽 = 峰值吞吐量 ≈ 20MB/s
100Mbps 单位是 bit ; 10M/s 单位是 byte ; 1byte = 8 bit , 100Mbps/8 = 12.5M/s
44、生产者调优
45、broker(服务器)
46、消费者
47、整体调优
(1)如何提升吞吐量
(2)数据精确一次
(3)合理设置分区数
(4)单条日志大于 1M
(5)服务器挂了
48、集群压力测试