Kafka消费者组静态成员(static consumer member)
Kafka 2.3发布后官网的Consumer参数中增加了一个新的参数:group.instance.id。下面是这个参数的解释:
A unique identifier of the consumer instance provided by end user. Only non-empty strings are permitted. If set, the consumer is treated as a static member, which means that only one instance with this ID is allowed in the consumer group at any time. This can be used in combination with a larger session timeout to avoid group rebalances caused by transient unavailability (e.g. process restarts). If not set, the consumer will join the group as a dynamic member, which is the traditional behavior.
大致意思是:它是用户指定的一个consumer成员ID。每个消费者组下这些ID必须是唯一的。一旦设置了该ID,该消费者就会被视为是一个静态成员(Static Member)。静态成员配以较大的session超时设置能够避免因成员临时不可用(比如重启)而引发的Rebalance。由此可见,消费者组静态成员是2.3版本新引入的一个概念,主要是为了避免不必要的Rebalance。
Rebalance Recap
之前我们在Kafka消费者组一文中讨论过Rebalance机制。它的主要作用是为消费者组下所有成员分配分区。Client端和Broker端需要同时参与到Rebalance过程。在Broker端,Coordinator组件负责处理成员管理,比如处理组成员发送的JoinGroup请求、SyncGroup请求、Heartbeat请求和LeaveGroup请求;在Client端,Leader Consumer成员接收Coordinator发送的成员订阅信息,然后根据一定的策略(Range/Round-Robin/Sticky/自定义)制定分配方案。
Rebalance发生的条件有三个:
- 成员数量发生变化,即有新成员加入或现有成员离组(包括主动离组和崩溃被动离组)
- 订阅主题数量发生变化
- 订阅主题分区数量发生变化
其实,后两个条件可以合并成一个,即Rebalance触发条件只有两个:1. 成员数量发生变化;2. 订阅信息发生变化。
Rebalance的流程在那篇文章中也谈到了:首先,各个成员发送JoinGroup请求入组,Coordinator会等待一段时间等它们加入——这段时间由所有成员中max.poll.interval.ms的最大值来决定(在Kafka Connect中则是有专属的参数rebalance.timeout.ms来指定)。之后各成员发送SyncGroup请求等待Coordinator发送分配方案,然后开始正常消费。在消费的同时,各个consumer还会定期(heartbeat.interval.ms)上报心跳,告诉Coordinator组件它还活着。
Issues for Rebalance
在实际场景中,因为成员离组而发生的Rebalance应该算是最多的,但有些场景下的Rebalance是非常不合理的。比如我们公司就有这样的痛点:Consumer的处理逻辑发生变更,必须要更新代码重新上线,此时就要引发Rebalance,但其实重启Consumer也许只需要几分钟而已,也就是说我的消费只要中断几分钟就可以了,Kafka完全没必要为这个就触发一轮Rebalance,更没有必要重新分配分区,维持之前的分配方案足矣。虽然社区提供的Sticky分配方案在一定程度上能够缓解此问题,但Rebalance的Stop The World(STW)的特性还是决定了生产环境中Rebalance越少越好。
Static Member
在目前的Rebalance设计中,消费者组下的每个实例都会被Coordinator分配一个成员ID,即member.id。很多Kafka用户都有过这样的疑问:我能手动设置这个member.id吗?很遗憾,这个memberID是Kafka自动生成的,在静态成员被引入前,规则是client.id-UUID,这里的client.id就是Consumer端参数client.id的值,而且这个ID会随着每轮Rebalance发生变化的。换句话说,Coordinator无法持久化地保存某个consumer实例的member.id。我想这可能是制约Rebalance时所有成员必须强制重新加入的部分原因,因为Coordinator无法记住每个成员都是谁。如果你看源代码,可以发现在每次Client重启回来发送JoinGroup时,它会封装一个UNKNOWN_MEMBER_ID的空串,没有任何有意义的信息给到Broker端。Coordinator接收到后只能把它当做是一个全新的成员。相反地,如果member.id能够被记住,那么Coordinator就可以容忍它短暂的离线而不开启Rebalance,从而缩短消费者组整体不可用的时间窗口。
为此,社区于2.3和2.4版本引入了静态成员(Static Member)的概念以及一个新的Consumer端参数:group.instance.id。一旦配置了该参数,成员将自动成为静态成员,否则的话和以前一样依然被视为是动态成员。你可以认为这个新参数是一个要被持久化的新member.id。它依然不能由用户指定,构建规则是`group.instsance.id`-UUID。和member.id不同的是,每次成员重启回来后,其静态成员ID值是不变的,因此之前分配给该成员的所有分区也是不变的,而且在没有超时前静态成员重启回来是不会触发Rebalance的。
静态成员Rebalance条件
显然,静态成员触发Rebalance的难度要小于动态成员。如果使用了静态成员,现在触发Rebalance的条件变更为:
- 新成员加入组:这个条件依然不变。当有新成员加入时肯定会触发Rebalance重新分配分区
- Leader成员重新加入组:比如主题分配方案发生变更
- 现有成员离组时间超过了session超时时间:即使它是静态成员,Coordinator也不会无限期地等待它。一旦超过了session超时时间依然会触发Rebalance
- Coordinator接收到LeaveGroup请求:成员主动通知Coordinator永久离组。毕竟Kafka还是要提供方法让一个成员能够永远地退出组,此时重启Rebalance还是必要的
请求协议变更
为了支持group.instance.id,与消费者组相关的协议格式也要做对应的变化。我看了下官网,JoinGroup、SyncGroup、LeaveGroup和OffsetCommit请求的协议格式都做了相应的变更。比如JoinGroup请求的Request和Response格式都增加了group-instance-id字段,如下所示:
JoinGroup Request (Version: 5) => group_id session_timeout_ms rebalance_timeout_ms member_id group_instance_id protocol_type [protocols]
group_id => STRING
session_timeout_ms => INT32
rebalance_timeout_ms => INT32
member_id => STRING
group_instance_id => NULLABLE_STRING
protocol_type => STRING
protocols => name metadata
name => STRING
metadata => BYTESJoinGroup Response (Version: 5) => throttle_time_ms error_code generation_id protocol_name leader member_id [members]
throttle_time_ms => INT32
error_code => INT16
generation_id => INT32
protocol_name => STRING
leader => STRING
member_id => STRING
members => member_id group_instance_id metadata
member_id => STRING
group_instance_id => NULLABLE_STRING
metadata => BYTES
其他请求格式的变更也是类似的,这里就不贴了。
其他变更
鉴于目前静态成员短暂重启或不可用不会触发Rebalance的改动,社区对消费者组最大session过期时间也做了修改。之前Consumer端参数group.min.session.timeout.ms值是6秒——要想在这个时间内重启完一个应用通常都是很困难的,因此社区现在将该值默认值改为30分钟。这就是说,只要配置有静态成员的Consumer程序代码更新及重启在30分钟之内完成,Consumer Group就不会发生Rebalance。当然在这段时间内,该Consumer的消费进度会中断,但是分区分配方案不会发生变化。
总结
目前静态成员的部分功能已经集成进Kafka 2.3版本,还有一部分功能正在开发中,未来会进到2.4版本中。从目前的设计来看,静态成员机制能够帮助我们规避很多线上环境中本不必要的Rebalance,应该说是个很令人期待的新特性。同时,社区针对Rebalance的Stop The World酝酿一次大的修正,即所谓的增量协同式Rebalance(Incremental Cooperative Rebalance)。大致思想是允许单个consumer实例自行采用增量或渐进式的方式进行Rebalance,避免全局的STW。相关的代码正在开发中,后续我也会带来这方面的功能介绍。
Kafka消费者组静态成员(static consumer member)的更多相关文章
- 详细解析kafka之 kafka消费者组与重平衡机制
消费组组(Consumer group)可以说是kafka很有亮点的一个设计.传统的消息引擎处理模型主要有两种,队列模型,和发布-订阅模型. 队列模型:早期消息处理引擎就是按照队列模型设计的,所谓队列 ...
- Kafka消费者组再均衡问题
在Kafka中,当有新消费者加入或者订阅的topic数发生变化时,会触发Rebalance(再均衡:在同一个消费者组当中,分区的所有权从一个消费者转移到另外一个消费者)机制,Rebalance顾名思义 ...
- Kafka 消费者解析
一.消费者相关概念 1.1 消费组&消费者 消费者: 消费者从订阅的主题消费消息,消费消息的偏移量保存在Kafka的名字是__consumer_offsets的主题中 消费者还可以将⾃⼰的偏移 ...
- Kafka消费组(consumer group)
一直以来都想写一点关于kafka consumer的东西,特别是关于新版consumer的中文资料很少.最近Kafka社区邮件组已经在讨论是否应该正式使用新版本consumer替换老版本,笔者也觉得时 ...
- Kafka设计解析(十三)Kafka消费组(consumer group)
转载自 huxihx,原文链接 Kafka消费组(consumer group) 一直以来都想写一点关于kafka consumer的东西,特别是关于新版consumer的中文资料很少.最近Kafka ...
- kafka消费组、消费者
consumer group consumer instance 一个消费组可能有一个或者多个消费者.同一个消费组可以订阅一个或者多个主题.主题的某一个分区只能被消费组的某一个消费者消费.那么分区和消 ...
- kafka Poll轮询机制与消费者组的重平衡分区策略剖析
注意本文采用最新版本进行Kafka的内核原理剖析,新版本每一个Consumer通过独立的线程,来管理多个Socket连接,即同时与多个broker通信实现消息的并行读取.这就是新版的技术革新.类似于L ...
- kafka 消费组功能验证以及消费者数据重复数据丢失问题说明 3
原创声明:作者:Arnold.zhao 博客园地址:https://www.cnblogs.com/zh94 背景 上一篇文章记录了kafka的副本机制和容错功能的说明,本篇则主要在上一篇文章的基础上 ...
- kafka producer自定义partitioner和consumer多线程
为了更好的实现负载均衡和消息的顺序性,Kafka Producer可以通过分发策略发送给指定的Partition.Kafka Java客户端有默认的Partitioner,平均的向目标topic的各个 ...
随机推荐
- HTML JAVASCRIPT CSS 大小写敏感问题
html: 大小写不敏感 css: 大小写不敏感 javascript: 大小写敏感 但是 但是 但是 这三者是相互联系的, 所以合在一起使用的时候就产生了变化 ---- TagName, Clas ...
- Python——IO多路复用之select模块poll方法
Python——IO多路复用之select模块poll方法 使用poll方法实现IO多路复用 .├── poll_client.py├── poll_server.py└── settings.py ...
- CSP 2019游记 & 退役记
扶苏让我记录他AK CSP 的事实 ZAY NB!!! "你不配" 两年半的旅行结束了,我背着满满的行囊下了车,望着毫不犹豫远去的列车,我笑着哭了,笑着翻着我的行囊-- 游记 Da ...
- spark基础知识二
主要围绕spark的底层核心抽象RDD进行理解.主要包括以下几个方面 RDD弹性分布式数据集的概念 RDD弹性分布式数据集的五大属性 RDD弹性分布式数据集的算子操作分类 RDD弹性分布式数据集的算子 ...
- failed to execute /bin/bash: Resource temporarily unavailable的问题处理
[admin@localhost ~]$ sudo su - scloanLast login: Tue Jun 12 14:06:31 CST 2018 on pts/3su: failed to ...
- bat无线热点设置
netsh wlan set hostednetwork mode=allow ssid=happyla key=1234567890netsh wlan start hostednetwork
- [原创]UnLua Emmylua UE4开发环境搭建
前言 公司开发的第二个虚幻4项目已经上线了,慢慢趋于稳定.回想起开荒的日子,历历在目.从引擎脚本的选择,各工具(导表,协议生成...)的重构.开发, 引擎扩展(多骨骼支持,Notify扩展,技能编辑器 ...
- C++删除排序数组中的重复项
class Solution { public: int removeDuplicates(vector<int>& nums) { if (nums.empty()) { ; } ...
- Java随堂笔记三
今天学习了Java运算符的最后一部分 public static void main(String[] args) { //算数运算符:+ - * / % ++ -- // ...
- python实现Huffman编码
一.问题 利用二叉树的结构对Huffman树进行编码,实现最短编码 二.解决 # 构建节点类 class TreeNode: def __init__(self, data): "" ...