Kafka()

特点

  • 存取消息
  • 临时存储消息

应用场景

  • 异步处理
  • 系统解耦
  • 流量削峰(kafka单机吞吐量10w+,mysql单机只有几千)
  • 日志处理

模型

  • 生产者、消费者

两种模式

  • 点对点(一条消息只能被一个消费者消费)
  • 发布订阅(一条消息被多个消费者消费)

kafka集群必须有zookeeper

topic(主题):逻辑结构,类似mysql表,我们要在一个主题上存取数据

RabbitMQ 更适合业务异步解耦

RocketMQ 更适合金融事务场景

Kafka 更适合高吞吐日志流与实时计算

消费者组:将若干个消费者组合在一起,共同消费kafka中topic的数据

消费者组中活跃消费者数量小于等于topic分区数量

一个topic的一个分区只能由一个消费者消费,防止顺序混乱

消费者从kafka拉取数据需要offset

poll() 机制能保证你的程序在没活干时优雅地睡觉,有活干时瞬间起跳。

使用异步方式生产消息

  • 在发送消息出现异常时,能够及时打印出异常信息
  • 在发送消息成功时,打印kafka的topic名字,分区id,offset

同步:send(消息对象) future.get():阻塞等待返回

异步:send(消息对象,回调函数)

重要概念

  • broker
    一个kafka集群通常由多个broker组成,这样才能实现负载均衡
    无状态,通过zk来维护集群状态
    一个kafka的broker每秒可以处理数十万次读写,每个broker都可以处理TB消息而不影响性能

Kafka幂等性

两个概念

  • PID:每个Producer在初始化时,都会分配一个唯一PID,这个PID对用户透明
  • Sequence Number:针对每个生产者(对应PID)发送到指定主题分区的消息都对应一个从0开始递增的Sequence Number

问题:

生产者 retry 导致消息重复写入

解决:

Kafka Broker 会为每个 (PID, Partition)

维护一个期望的 seq(expectedSeq)。

只有当消息的 seq == expectedSeq 时,

Broker 才会接收并写入消息。

分区和副本机制

生产者分区写入策略

  • 轮询分区策略(默认)
    使用最多的策略,最大限度保证所有消息分配到一个分区
    如果生产消息时,key为null,则使用轮训算法均匀地分配分区
  • 随机分区策略
  • 按key分区分配策略
    根据key的hashcode取模,可以保证同一个key放入相同的分区
  • 自定义分区策略

乱序问题:

轮询分区策略会导致分区内有序,分区间顺序不保证

key分区可以缓解乱序问题,但会导致数据倾斜

实际中应该根据业务选择合适策略

消费者组的Rebalance机制

再均衡,确保消费者组下所有的consumer如何达成一致,分配订阅的topic的每个分区的机制

触发时机:

1、消费者组中消费者的个数发生变化

3、订阅的topic发生变化(本质还是分区改变了)

2、订阅的topic发生分区变化

再均衡不良影响:

消费者组中所有消费者都会协调在一起共同参与,kafka使用分配策略尽可能达到最公平的分配

过程会对消费者组产生非常严重的影响,所有消费者停止工作,直到再均衡完成

消费者分区分配策略

Range范围分配策略(默认)

确保每个消费者组的分区数量是均衡的(rangle范围分配策略针对每个topic)

RoundRobin轮询策略

按照字典序排序(topic和分区的hashcode进行排序),然后通过轮询方式逐个将分区以此分配给每个消费者

粘性分配策略

1、分区尽可能均匀

2、在发生再均衡的时候,分区的分配尽可能与上一次分配保持相同(非全局分配而是局部调整)

副本机制

冗余备份,当某个broker上的分区数据丢失时,依然保证数据可用性,因为其他的broker上的副本是可用的

生产者的acks参数

0:不等待broker确认,直接发送下一条数据,性能最高,可能存在数据丢失问题

1:等待leader副本确认接收后,才会发送下一条数据,性能中等

-1(all):等待所有副本已经将数据同步后,才会发送下一条数据,性能最差

根据业务选择合适参数

分区中有leader和follower概念,为了确保消费者消费的数据是一致的,只能从分区leader去读写消息,follower的事情就是同步数据

API

高级API

直接让kafka帮助管理、处理分配、数据管理

不控制offset,不能从指定位置读取

不能细化控制分区、副本、ZK等

低级API

编写程序自己控制逻辑

自己控制offset,能自定义实现功能,实现复杂

可以指定消费者的topic分区,消费特定数据分区

监控工具Kafka-eagle

监控管理工具

Kafka原理

分区的leader与follower

针对分区(partition)

自动将leader均匀地分配在不同broker中

leader负责读写,follower负责备份(容灾),还有重新选举

leader出现故障,会在follower会选举新leader

AR、ISR、OSR

leader挂掉之后需要选取新的leader

AR(assigned Replicas):分区的所有副本

ISR(In-sync-replicas):所有与leader副本保持一定程度同步的副本

OSR(Out-of-Sync-replicas):同步滞后过多的副本(或者挂掉的follow副本)

leader选举

如何确定某个partition是leader、哪个partition是follower:

随机选取,尽量均匀

某个leader崩溃了如何快速确定另外一个leader:

因为kafka吞吐量高、延迟低,选取一定要快

选取范围:ISR

controller:启动时在所有broker中选择一个controller

  • 所有partition的leader选举都由controller决定
  • controller会将leader的改变直接通过RPC的方式通知对应Broker
  • 通过ISR,选择存活备份,否则随便选,如果备份全宕机,新leader为-1

leader负载均衡

preferred replica:优先副本

生产、消费数据工作流程

生产者优先找到对应分区的leader

先找leader,采用拉模式(默认从最新数据读取)

数据存储形式

  • 一个topic由多个分区组成
  • 一个分区由多个segment组成
  • 一个segment由多个文件组成
    • log:存储数据
    • index:存储offset索引(稀疏索引)
    • timeindxe:存储时间索引

LEO:log-end-offerset日志最后的offset(下一条待写入消息的offset)

定期清理

消息默认7天后开始清理,一次删除一个segment段的日志文件

kafka日志管理器,根据kafka配置,决定那些文件可以被删除

消息不丢失机制

生产者数据不丢失

通过多个副本,leader副本挂了,可以在ISR集合中快速选出新leader副本

生产者数据不丢失

ACK机制,设置为all(-1):保证所有副本数据同步后返回确认

发送数据两种方式:同步(等待ack返回)、异步(提供一个回调函数)

消费者数据不丢失

只要每个消费者记录好offset值即可

消息丢失:自动提交的offset容易出现(消费数据失败,offset已经变化(存在zk中))

重复消费:自动提交offset时,更新zk中offset失败

解决:使用低级api,直接手动管理offset,不将offset存入zk而是从mysql拉取(通过事务保证消息和offset的原子性)

消息传递的语义

at-most-once:最多一次(只管把数据消费到,不管有没有成功,可能会有数据丢失)

at-least-once:最少一次(有可能出现重复消费)

exactly-once:仅有一次(事务性的保障,保证消息有且仅被处理一次)

数据积压

虽然很快,但是网络拥堵,外部IO(消费者进程)也会导致积压,破坏数据实时性

问题一:partition不够

解决:增加partition,增加消费者

问题二:消费者消费慢

解决:一次拉取多条数据,批量操作;通过线程池处理任务

问题三:消费者挂了(比如fullGC)

解决:恢复消费者

问题四:Rebalance 导致暂停消费

解决:增量式rebalance(新版)

问题五:下游故障(mysql挂了,不提交offset)

解决:恢复mysql

避免:监控指标(出现积压赶紧排查问题)

kafka数据清理

日志删除:按照指定的策略直接删除不符合条件的日志

日志压缩:按照消息的key进行整合,有相同key的但有不同value值,只保留最后一个版本

混合模式

以segment为单位进行定期清理

定时删除日志:

  • 基于时间的保留策略
    默认保存7天(168小时)
  • 基于日志大小的保留策略
  • 基于日志起始偏移量的保留策略

kafka事务

幂等性只能保证单次会话幂等性

生产者挂了,重试(新会话,新PID)

解决:引入全局唯一TransactionID

并将PID和TransactionID绑定

当生产者挂了,通过TransactionID拿到自己之前的PID

通过:Transaction coordinator组件管理

消费者事务:不保证,自己保证

相关推荐
qq_2975746714 小时前
第十四篇:RabbitMQ监控与日志分析——快速排查线上问题
分布式·rabbitmq·ruby
小的~~15 小时前
CentOS7安装CDH6.3.2
hive·hdfs·kafka
2401_8401922717 小时前
k8s的crd、operator、cr分别是什么?
运维·分布式·kubernetes·prometheus
covco18 小时前
星链引擎矩阵系统:分布式任务调度与万级账号批量作业自动化技术实践
分布式·矩阵·自动化·批量作业
Little Tomato21 小时前
深入浅出高并发:从 JVM 锁竞争到分布式事务的性能博弈
jvm·分布式
zshs00021 小时前
从 Raft 到 MySQL:我是怎么推导出半同步复制原理的
数据库·分布式·mysql
凯瑟琳.奥古斯特21 小时前
页面置换算法详解与对比
开发语言·分布式·职场和发展
KANGBboy1 天前
hadoop冷热数据分离
大数据·hadoop·分布式
skilllite作者1 天前
Evotown——开启本地化、可验证的AI智能体进化新时代
人工智能·分布式·安全·搜索引擎·agentskills