kafka 教程(四)-原理进阶
kafka 最初由 Linkedin 公司开发,是一个 分布式、支持分区、多副本的,基于 zookeeper 协调的分布式发布订阅消息系统,该公司在 2010 年将 kafka 贡献给 apache 基金会,1年后升级为顶级项目。
kafka 由 scalar 语言编写, 并提供了多种语言的接口。
kafka 特性
kafka 是一个分布式系统,天然具有分布式的所有优势。
1. 高吞吐量:支持每秒百万级的消息处理,最低只有几毫秒的延迟
2. 可扩展性:集群优势
3. 容错:集群优势,允许部分节点挂机
4. 持久化:消息被持久化到磁盘,并支持副本
kafka 使用场景
kafka 可以使用到许多场景,包括实时和离线,这里举几个例子,以便扩展你的思维。
1. 日志存储:将各个服务的 log 统一存储到 kafka,并提供通用接口,方便各种调用,如 hadoop
2. 消息系统:kafka 本身就是消息队列
3. 用户活动跟踪:将各种 web / app 的用户行为存储到 kafka,用于实时监控分析,或者迁移到 hadoop、hdfs 等做离线分析
4. 运营监控:如各种大屏展示
5. 流式处理:如 spark storm
kafka 基础架构
kafka 的特点在于 发布订阅,其机制如下图
producer 向 kafka send 消息,send 之前,会对消息进行分类,即 topic
consumer 会与 kafka 建立长连接,当 topic 中有新的消息时,所有 consumer 会自动接收到;当然 consumer 也可以主动拉取历史消息
Broker
集群中的一个节点,很多核心的逻辑部署在 broker 上
controller:中央控制器,管理分区和副本状态,并负责管理 分区 的重新分配,包括 分区选举
Isr:同步副本
[root@localhost kafka_2.11-0.9.0.0]# bin/kafka-topics.sh --describe --zookeeper localhost:2191 --topic sq
Topic:sq PartitionCount:4 ReplicationFactor:3 Configs:
Topic: sq Partition: 0 Leader: 0 Replicas: 0,10,11 Isr: 0,10,11
Topic: sq Partition: 1 Leader: 10 Replicas: 10,11,12 Isr: 10,11,12
Topic: sq Partition: 2 Leader: 11 Replicas: 11,12,0 Isr: 11,12,0
Topic: sq Partition: 3 Leader: 12 Replicas: 12,0,10 Isr: 12,0,10
topic sq 4个分区,3个副本,每个分区有个 leader,作为读写的首选 partition
producer 详解
producer 处理流程如下图
以下是有顺序的解释
1. ProducerRecord 代表数据,数据必须包含 topic 和 value,key 和 partition 可选 --- 创建数据
2. Serializer 代表格式化 key 和 value --- 格式化
3. Partitioner 代表分区策略 --- 根据 key 计算分区
// 如果 ProducerRecord 中指定了分区,此步忽略,直接返回指定的 partition
4. 有了分区和topic,把该消息添加到对应的 topic 和分区上的 batch
5. 专有线程负责发送 batch record 到 broker
6. broker 接收到消息,返回一个 response
// 如果写入成功,返回的是 RecordMetadata,包括 topic、partition、offset
// 如果写入失败,返回 error,此时 producer 会自动重复发几次,直到 producer 返回 error
Producer 发送消息有 3 种方式
1. 立即发送:只管发送给 kafka,不关心是否发送成功
// 即使不成功,程序也不会提示;不过大部分情况是成功的,因为 kafka 具有高可用性,且自动重试;但不保证一定成功
2. 同步发送:通过 send 方法发送消息,并返回 future 对象,get 方法会等待 future 对象,检验是否发送成功
3. 异步发送:通过带有回调函数的 send 方法发送消息,当 producer 收到 broker 的 response 会触发回调函数
consumer 详解
由于 consumer 处理消息 和 commit 提交反馈这两个动作不是原子性的,或者说不在一个事务内,由此 consumer 具有 3 种消费模式。
1. 最多一次:表示这条消息最多被消费一次,可能是 0 次
// 客户端收到消息后,在处理消息前,自动提交,这样 kafka 就会认为这条消息被消费过了,offset 会加一,这样这条消息就不会再被消费,也就是只能被消费一次
实现方式: 较小时间间隔内自动提交
设置 enable.auto.commit为ture
设置 auto.commit.interval.ms为一个较小的时间间隔.
client 不要调用 commitSync(),kafka 在特定的时间间隔内自动提交。
2. 最少一次:表示这条消息最少被消费一次,可能是多次
// 客户端收到消息后,先处理消息,处理完了再提交,可是处理过程中提交前,kafka 服务可能挂了,或者网络原因等各种异常,导致没有提交成功,kafka 会认为这条消息没被消费
实现方式:手动提交或者较大时间间隔自动提交
方法一
设置 enable.auto.commit 为false
client 调用 commitSync(),增加消息偏移; 方法二
设置 enable.auto.commit 为ture
设置 auto.commit.interval.ms 为一个较大的时间间隔.
client调用commitSync(),增加消息偏移;
3. 正好一次:表示这条消息只好被消费一次
// 保证处理消息和提交在一个事务内
实现方式比较麻烦,参考 Kafka client 消息接收的三种模式
在消费者消费过程中, kafka 会使用 offset 来记录当前消费的位置
kafka 分区机制
1. broker 端支持 topic 分区,一个 topic 可以有多个分区,一个分区可以有多个副本,一个分区的多个副本分布在不同 broker 上;
2. partition 使得 kafka 作为 MQ 可以横向扩展,分区越多,吞吐量越大;
3. 副本中有一个 leader,其他都是 follower,message 先写到 leader 上,再由 leader 同步到 follower;
4. 一个 partition 中 message 的顺序就是 producer 发送的顺序,所以一个 partition 是一个有序的队列;
5. 最晚被接收的 message 会被最后消费;
6. partition 中每个 message 都有一个序列号叫 offset,作为消息的标识符;
7. 在 broker 中每个分区是一个目录,目录名字规则为 topic-副本序号,副本序号从 0 开始;
下面的五个文件和 partition 存在一起,都各有用处。
cleaner-offset-checkpoint:存了每个log的最后清理offset,log 指的是消息
meta.properties:broker.id 信息
recovery-point-offset-checkpoint:表示已经刷写到磁盘的记录。recoveryPoint以下的数据都是已经刷 到磁盘上的了。
replication-offset-checkpoint: 用来存储每个replica的HighWatermark的(high watermark (HW),表示已经被commited的message,HW以下的数据都是各个replicas间同步的,一致的。)
8. 每个 partition 由多个大小相等的 segment (段)组成,segment 是消息的真实载体,每个 segment 的消息数量不一定相等;
9. 每个 segment file 由两部分组成:index 和 log,分别存放 索引 和 数据
00000000000004909731.index
00000000000004909731.log // 1G文件--Segment
00000000000005048975.index // 数字是Offset
00000000000005048975.log
10. index 和 log 映射关系
.index文件存放的是message逻辑相对偏移量 (相对offset=绝对offset-base offset)与在相应的.log文件中的物理位置(position);
但.index并不是为每条message都指定到物理位置的映射,而是以entry为单位,每条entry可以指定连续n条消息的物理位置映射
例如:假设有20000~20009共10条消息,.index文件可配置为每条entry指定连续10条消息的物理位置映射,该例中,index entry会记录偏移量为20000的消息到其物理文件位置,一旦该条消息被定位,20001~20009可以很快查到。
每个entry大小8字节,前4个字节是这个message相对于该log segment第一个消息offset(base offset)的相对偏移量,后4个字节是这个消息在log文件中的物理位置。
11. segment 文件命名规则:partion 全局的第一个 segment 从 0 开始,后续每个 segment 文件名为上一个 segment 文件最后一条消息的 offset 值。数值最大为64位long大小,19位数字字符长度,没有数字用0填充。
12. 多个 segment 方便 old message 被删除;
13. segment 文件的生命周期有 kafka 参数决定;
消费组与分区的重平衡-reblance
之前讲到了消费者组的作用,不熟悉的看我之前的博客。
如果一个新的消费者加入消费者组,那么他应该会被分配 1 个或多个分区,而这些分区原来是由其他消费者负责;
当一个消费者离开消费组时,他所消费的分区会被分给其他消费者;
这种机制叫做 重平衡。
这是 kafka 的一个重要特性,它保证了高可用和横向扩展。
缺点
1. 在 重平衡 期间,所有消费者不能进行消费,导致整个消费组不可用;
2. 重平衡 会导致原来的消费者状态过期,消费者需要重新更新状态,导致消费性能降低
如何监控消费者
消费者需要定期向一个作为 组协调者 的 broker 发送心跳,注意 这个 broker 不是特定的,每个组的 broker 可能都不同;
消费者拉取或者提交时,就会发送心跳; 【老版本】
如果超过一定时间没有发送心跳,那么他的会话 session 就会过期,触发 重平衡。
从上可以看出,从宕机到被监测到宕机,是有一个时间段的,这段时间这个消费者负责的分区都没有消息被消费;
所以通常 我们需要 优雅的关闭,这样消费者会发生 离开 的消息到 组协调者,从而避免这个空白期
可能有些同学会发现,上面讲的定期发送心跳和拉取提交发送心跳似乎矛盾了,确实如此,所以新版的 kafka 将发送心跳和拉取消息进行分离,拉取消息的频率不影响心跳发送。
另外更高版本的Kafka支持配置一个消费者多长时间不拉取消息但仍然保持存活,这个配置可以避免活锁(livelock)。活锁,是指应用没有故障但是由于某些原因不能进一步消费。
kafka 与 zookeeper 关系
zookeeper 起到协调控制的作用。
1. 管理 broker 和 consumer 的加入与离开
2. 触发负载均衡,当有 broker 或者 consumer 加入或离开时,会触发负载均衡算法,是的一个 消费组 内的 多个消费者 消费平衡。
3. 维护消费关系 和 每个 partition 的消费信息
1. 每个broker启动后会在zookeeper上注册一个临时的broker registry,包含broker的ip地址和端口号,所存储的topics和partitions信息。
2. 每个consumer启动后会在zookeeper上注册一个临时的consumer registry:包含consumer所属的consumer group以及订阅的topics。
3. 每个consumer group关联一个临时的owner registry和一个持久的offset registry。对于被订阅的每个partition包含一个owner registry,内容为订阅这个partition的consumer id;同时包含一个offset registry,内容为上一次订阅的offset。
新版的 kafka 已经把 consumer 部分信息移到 kafka 上了。
参考资料:
https://blog.csdn.net/lingbo229/article/details/80761778 史上最详细
https://blog.csdn.net/luanpeng825485697/article/details/81036028 很不错的教程,原理与实操都比较深入
https://www.jianshu.com/p/d3e963ff8b70
kafka 教程(四)-原理进阶的更多相关文章
- 黄聪:Microsoft Enterprise Library 5.0 系列教程(四) Logging Application Block
原文:黄聪:Microsoft Enterprise Library 5.0 系列教程(四) Logging Application Block 企业库日志应用程序模块工作原理图: 从上图我们可以 ...
- kafka知识体系-kafka设计和原理分析
kafka设计和原理分析 kafka在1.0版本以前,官方主要定义为分布式多分区多副本的消息队列,而1.0后定义为分布式流处理平台,就是说处理传递消息外,kafka还能进行流式计算,类似Strom和S ...
- kafka集群原理介绍
目录 kafka集群原理介绍 (一)基础理论 二.配置文件 三.错误处理 kafka集群原理介绍 @(博客文章)[kafka|大数据] 本系统文章共三篇,分别为 1.kafka集群原理介绍了以下几个方 ...
- Apache Kafka教程
1.卡夫卡教程 今天,我们正在使用Apache Kafka Tutorial开始我们的新旅程.在这个Kafka教程中,我们将看到什么是Kafka,Apache Kafka历史以及Kafka的原因.此外 ...
- Elasticsearch入门教程(四):Elasticsearch文档CURD
原文:Elasticsearch入门教程(四):Elasticsearch文档CURD 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接: ...
- CRL快速开发框架系列教程四(删除数据)
本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...
- 手把手教从零开始在GitHub上使用Hexo搭建博客教程(四)-使用Travis自动部署Hexo(2)
前言 前面一篇文章介绍了Travis自动部署Hexo的常规使用教程,也是个人比较推荐的方法. 前文最后也提到了在Windows系统中可能会有一些小问题,为了在Windows系统中也可以实现使用Trav ...
- Windows OS上安装运行Apache Kafka教程
Windows OS上安装运行Apache Kafka教程 下面是分步指南,教你如何在Windows OS上安装运行Apache Zookeeper和Apache Kafka. 简介 本文讲述了如何在 ...
- C#微信公众号开发系列教程四(接收普通消息)
微信公众号开发系列教程一(调试环境部署) 微信公众号开发系列教程一(调试环境部署续:vs远程调试) C#微信公众号开发系列教程二(新手接入指南) C#微信公众号开发系列教程三(消息体签名及加解密) C ...
随机推荐
- python27 错误汇总
一.TypeError: object of type 'NoneType' has no len() 解决的方法: 源代码:resp_data = None (None是一个空的对象) 修改后代码 ...
- Docker入门-Dockerfile的使用
使用Dockerfile定制镜像 镜像的定制实际上就是定制每一层所添加的配置.文件.我们可以把每一层修改.安装.构建.操作的命令都写入一个脚本,这个脚本就是Dockerfile. Dockerfile ...
- Docker入门-介绍和安装
Docker容器 Docker是什么 Docker最初是dotCloud公司创建人Solomon Hykes在法国期间发起的一个公司内部项目,它是基于dotCloud公司多年云服务技术的一次革新,并于 ...
- zoopkeeper 的ACL操作
1.创建一个变量存放模式信息, private static final String MODE = "digest"; //ACL模式 2.在一个类的构造函数内放入初始化信息 ...
- 解决Oracle XE报错ORA-12516(oracle回话数超出限制)
本地安装的oracleXEUniv—oracle特别版,免费用户可以自由使用,但有连接数量和存储限制. 最近遇到一个问题,当我的SSM项目连接本地数据库oracleXE后,我的navicat再连接时就 ...
- PDS常用快捷键
绿色在Layout和Router中共用 1.PDS常用快捷键:2019-07-28 17:06:07 快捷键 说明 备注 shiftt + 左键双击 布线状态下,进行过孔放置 ctrl + 左键双 ...
- leetcode 289生命游戏
class Solution { public: vector<vector<,},{,},{,},{,-},{,-},{-,-},{-,},{-,}}; void gameOfLife( ...
- Git检出和提交至远程仓库
步骤一:首先需要一个Github账号,还没有的话先去注册:https://github.com/,我们使用Git需要先安装Git工具,这里给出下载地址:https://git-for-windows. ...
- Jmeter(十二)响应断言之响应文本和响应信息的差别
在Jmeter的后置处理器中添加响应断言, 要测试的响应字段中有两个很难区分的选项, 响应文本和响应信息. 我做了两个小实验来进行区别. 1. 用Fiddler捕捉了一个POST请求, 其响应是suc ...
- LoadRunner参数化使用mysql数据源
因为默认是没有mysql驱动的,因此需要在网上下载一个mysql驱动 1. 在网上下载一个是MYSQL数据库的ODBC驱动程序:mysql-connector-odbc-3.51.20-win32.e ...