Kafka 笔记02

书接上文…

Kafka架构

2.6 提交和偏移量

总结了一些概念,还有自己的一些理解.
poll()方法!核心方法之一! 每次调用poll()方法,总返回由生产者写入 Kafka 但还没有被消费者读取过的记录.

提交

更新分区当前位置的操作,叫提交.比如,北京的城六区的GDP为10000e,当前处理了1000e;这个1000e就是偏移量,需要提交这个偏移量通知.

再均衡

假如广州GDP为20000e,当前处理了500e;如果消费者正常管理,就不需要care;但是如果有新消费者加入,比如曹操也想分一杯羹,那么,就要再均衡.再均衡后,每个消费者可能分配到新的分区,而不是之前处理的那个.如果想继续,那么需要读取500e,这500e已经消费了,不能二次消费.

如果提交的是500e,但是在此期间,朱元璋又消费了10e,再平衡是以500e作为基准,这10e自然要再次管理一次.处理偏移量,对消费者的影响是很大的,要慎重.

值得注意的是,如果topic只有一个分区,比如西安,只有一个分区,那么是无法添加新消费者去分担任务的.这就杜绝了再平衡的可能.

几种提交偏移量的方法
自动提交

如果 enable.auto.commit 被设为 true,那么每过 5s,消费者会自动把从 poll() 方法接收到的最大偏移量提交上去.提交时间间隔由 auto.commit.interval.ms 控制,默认值是 5s.
优点:自动
缺点:重复处理

提交当前偏移,commitSync

优点:不会重复
缺点:会遗漏

异步提交:commitAsync

只管发送提交请求,无需等待broker响应.
提交,然后继续干活;在成功提交或者碰到无法修复的错误前,commitSync() 会一直重试,但是 commitAsync()不会,这也是 commitAsync() 不好的一个地方.
比如,西安的1000e已经被处理了,提交信息;但是服务器无法接收;然后到了1500e,成功提交了;此时,1000e提交成功,那么1000e-1500e的数据,会重复处理;出现重复消息.

同步+异步提交
提交指定的偏移

2.7 再均衡器

广州,朱元璋一个人管理怕出问题,加朱棣一起管理;再均衡之前,需要做一些清理工作.比如,朱元璋用了1000e,这是偏移量,然后又消费了100e,就停止了,这100e还不足以打报告;加了朱元璋;那么就需要处理在缓冲区积累的100e.这时候,需要再均衡器来发挥作用了.

// ConsumerRebalanceListener, 需要实现两个方法
public void onPartitionsRevoked(Collection<TopicPartition> partitions) //在再均衡开始之前和消费者停止读取消息之后被调用;提交偏移量
public void onPartitionsAssigned(Collection<TopicPartition> partitions) //重新分配分区之后和消费者开始读取消息之前被调用;确定重新分配后的偏移量

2.8 从特定偏移量开始处理记录

poll() 方法从各个分区的最新偏移量处开始处理消息.
seekToBeginning(Collection tp) 和 seekToEnd(Collection tp)从开头末尾读取消息.
也有查找特定偏移量的 API,可以前进后退若干消息.

2.9 如何退出

如果确定要退出循环,需要通过另一个线程调用 consumer.wakeup() 方法.如果循环运行在主线程里,可以在 ShutdownHook 里调用该方法.
consumer.wakeup() 是消费者唯一一个可以从其他线程里安全调用的方法.

2.10 反序列化器

和序列化器一样,在其他地方有介绍,就不喧宾夺主了.

2.11 独立消费者

只需要一个消费者,从一个主题的所有分区或者某个特定的分区读取数据.比如,西安由刘秀管理,广州由朱元璋管理这个时候就不需要消费者群组和再均衡了,只需要把主题或者分区分配给消费者,然后开始读取消息并提交偏移量.
此时,不用订阅主题,只需要为自己分配分区即可.
一个消费者,可以订阅主题并加入消费者群组,或者为自己分配分区,但不可二者兼得.

++++++++++++++++++++++++++++++++分割线++++++++++++++++++++++++++++++++

3 深入Kafka

这一节是非常核心的…主要回答了几个问题:kafka如何复制? 如何处理来自生产者和消费者的请求?存储细节?我反反复复看了几遍,希望能给大家带来一些启发.

3.1 集群成员关系

参考了链接[1].
这一个小节我自己补充了一些,以我们的图为案例,来介绍一下.

现在,有1个producer,分为 北京上海广州西安 4个topic;北京每年生产35000eGDP(信息),上海36000e,广州25000e,西安10000e;

每个topic都可以被划分成一个或者多个分区(至少有一个分区),它是topic物理上的分组,在创建topic的时候指定一个Partition只对应一个Broker,一个Broker可以管理多个Partition.

这里,北京上海广州的体量大,分成2个分区(对应的北京:城六区&郊区,上海:浦东+其他,广州:天河黄埔+其他,西安:全部),每个区的信息都有3个replication.

有三个中介broker,张三李四王五,是各个分区组选出来的;分别管理不同分区.

kafka利用zookeeper来维护集群成员信息.每一个broker都有一个唯一标识符;broker启动时,向zk注册;当broker移除时,监听broker列表的kafka组件会被告知该broker gg了.

broker也有群组,如图所示,三个broker,中介,张三李四王五,隶属于东亚居委会broker群组.

消费者分为4个群组,分别对应4个topic,唐代群组,李世民+李隆基组合;西汉群组,刘彻+刘邦;大明群组,朱元璋一个人搞定;东汉群组,刘秀一个人搞定;

controller,也是broker,是broker中挑出来的.控制器 = broker + 分区leader选举功能.控制器只有一个.

3.2 控制器

第一个启动的broker自动成为controller.比如张三先来,那么张三就是controller.

controller也会gg.假如张三有事,调离该东亚居委会了,其他broker得到消息,会开始竞争成为新的controller,毕竟controller有权决定分区的leader hhh.
新leader上位后,老leader传来的消息都会被无视.假如李四财大气粗,占尽先机,就会成为下一任controller.

现在是李四当controller的情况.
假如张三回来了,也只能当小弟了.过了一段时间,张三年老体衰,长期缺勤,电话也打不通(没有心跳了),就认为张三这个broker退休了.

注意,张三旗下,有3个leader,北京城六区+郊区,西安全区;这三个leader也随着张三退休而gg了;因此北京城六区+郊区,西安全区;,需要新leader;controller可以确定谁当下一任话事人.

选好后,新话事人开始处理生产者和消费者的请求,follower开始复制消息.

当controller发现一个broker加入居委会,比如孙悟空要加入居委会,那么controller会检查孙悟空,是否有现有分区副本;比如北京城六区的副本等.如果有,会通知所有broker,孙悟空这个新broker也要从leader那复制消息;毕竟弼马温也要听玉帝的 hhh

3.3 复制

复制是kafka的关键!
kafka用topic组织数据,每个主题分为若干个分区.比如北京,分为城六区+郊区(ummm).城六区和郊区都有3个副本,都在不同的broker上;每个broker可以保存许多不同topic的分区的副本

两种副本:

leader 副本:所有produer和consumer请求都要过leader的手; 此外leader要搞清楚,哪个follower最紧跟自己,最一致;

follower 副本:所有follower都要紧跟leader脚步,保持一致;if leader gg,follower会各显神通,成为新leader.

if follower没有和leader保持一致,比如信号不好,理解不到位,或者急于上位,抢跑在leader前面,都会出问题;leader也不会青睐他们.

无论是理解不到位还是抢跑,在leader看来都是不同步的,async的;那么,当leader gg 了,都不会让他们成为新leader,毕竟理解不到位嘛.

最一致的follower,小弟,会成为同步的副本,也就是二把手,老leader下线了,只有二把手才能上位.

除了当前leader之外,每个分区还有一个首选首领——创建主题时选定的首领就是分区的首选首领;之所以把它叫作首选首领,是因为在创建分区时,需要在 broker 之间均衡首领:

比如,在创建分区的时候,张三, broker0, 占据了北上广西的全部leader;那么其他broker会不高兴,也不安全,万一张三挂了,其他的都要选举,都要抢leader,很浪费资源;而且张三也会很累;因此,会将leader均分,大家都有肉吃,就不会怨声载道了.

现在我们假设,上海浦东新区的leader初始leader其实在张三那,但是为了平衡,给了李四;if李四挂了,而且,auto.leader.rebalance.enable = true,可以自动再平衡,那么只要首选leader不是当前leader,而且紧跟leader脚步,即使不是二把手,也会成为新leader,毕竟资格老+同步.所以,如果存在几个二把手,这几个都十分同步,那么首选首领优先级最高.

3.4 处理请求

broker 的大部分工作是处理客户端、分区副本和控制器发送给分区首领的请求.
kafka有二进制协议,制定了请求消息的格式,如何效应,如何处理错误.

标准消息头包含下面几个信息:
request type
request version
correlation id
client id

broker会在它监听的端口上运行acceptor线程,创建连接,并把它交给processor线程处理.

几种常见请求:

生产请求:生产者发送的请求,包含客户端要写入broker的消息.
获取请求:消费者和跟随着副本需要从broker读取消息时发送的请求.

生产请求和获取请求都必须发送给分区的首领副本;换句话说,生产请求(工作)和获取请求(工作)都要和领导汇报;
如果 broker 收到一个针对特定分区的请求,而该分区的首领在另一个 broker 上,比如张三收到上海浦东新区的请求,应该告诉李四区处理;
又或者,针对特定分区的获取请求被发送到一个不含有该分区首领的 broker上,比如针对南京城区的请求,发送到张三那,但是张三不管南京,也会报错.

客户端如何知道往哪里发送请求?客户端也要发送请求,元数据请求,从而获取这些主题所包含的分区、每个分区都有哪些副本.以及哪个副本是首领.

元数据一般会缓存下来,并且定期刷新数据.

3.4.1 生产请求

acks这个参数,指定了需要多少个 broker 确认才可以认为一个消息写入是成功的.
包含leader副本的broker,比如张三,有北京的leader副本,收到生产请求后会作验证:
1,发送data的用户是否有主题写入的权限?比如张三,收到南京的GDP(消息),他会考虑南京好像不是主题中的一个,没有主题写入权限,因此不会allow.
2,acks这个参数,见ack.
3,ack=all时,是否有足够的同步副本保证消息的写入.

之后消息写入本地磁盘.Linux中,消息写入到文件系统缓存中,不保证什么时候刷新到磁盘上.kafka依赖复制功能保证消息的持久性,不会一致等待数据被写入到磁盘中

消息写入分区的leader,broker会开始check acks的配置参数;比如西安新增了1000eGDP,需要写入西安分区;消息到了分区首领后,broker发现acks=0|1,那么broker会汇报,ok了;如果broker发现acks=all,那么请求被保存在叫做炼狱的缓冲中,直到leader分区和小弟分区都复制了1000eGDP之后,才ok

3.4.2 获取请求

客户端发送请求,向 broker 请求主题分区里具有特定偏移量,那么需要考虑以下因素:

数量限制
比如李世民 向broker 张三请求北京城六区里10000e到15000e的GDP(信息)用来打击游牧民族;客户端指定broker最多从一个分区返回多少,就好比最多拨款1000e,你申请5000e,没门,只给1000e;这个限制是为了让客户端为broker返回的数据分配足够多内存,如果数据过多,可能会爆内存;好比1000eRMB的纸币,李世就1栋楼,装不下.

偏移量
请求会先到北京城六区leader,然后看消息是否ok.比如指定的偏移量是否存在?要是申请的是15000e到20000e这区间的GDP,就不行,北京城六区总共才15000e,哪有15000-20000e的区间.

零复制
如果李世民只请求5000e-6000e这个区间的预算,broker张三,会按照1000e的限制,发送信息给客户端;零复制,直接发送,步需要中间缓存.避免字节复制,不需要管理内存缓冲,性能更好.

下限
此外也可以设定下线,比如拨款1块,啥都干不了,不如不拨款,传递1块钱,成本可能都不止1块了.为了保证下限,可能需要累计信息一次性发送

但是要注意,不是所有数据都可以被consumer读取;只能读取已经被写入所有同步副本的信息;比如北京城六区15000e,另外两个小弟,一个只复制了14000e,一个步子大,干到16000e,那么14000-15000区间的数据是不能调用的,因为副本不够的信息,是不安全的.

3.4.3 其他request

3.5 物理存储

++++++++++++++++++++++++++++++++分割线++++++++++++++++++++++++++++++++

4 可靠的数据传递

可靠性,不只是某个个体的事情. Kafka 管理员、 Linux 系统管理员、网络和存储管理员以及应用程序开发者,必须一起努力;结合我们部门最近出的bug,确实是这么回事.

4.1 可靠性保证的含义

数据库的ACID,就是典型的可靠性保证
kafka的可靠性保证:
分区消息顺序.按照偏移量排序
消息被写入到所有副本,才被认为是已经提交的.
只要还有一个副本是活跃的,那么已经提交的消息就不会丢
消费者只能读取已经提交的消息

4.2 复制

前面已经介绍了,就不多说了

4.3 broker配置

broker 有 3 个配置参数会影响 Kafka 消息存储的可靠性

4.3.1 复制系数:replication.factor

主题级别的配置参数是replication.factor,而在broker级别则可以通过default.replication.factor来配置自动创建的主题

4.3.2 不完全的首领选举

unclean.leader.election 只能在 broker 级别(实际上是在集群范围内)进行配置;默认true;当分区leader下线时,一个同步副本会被选为新首领.如果在选举过程中没有丢失数据,也就是说提交的数据同时存在于所有的同步副本上,那么这个选举就是"完全"的.

但是如果所有副本都是非同步的,how?

1,不同步副本不提升–>罢工很久直到旧leader复原; 2,提升follower,数据不一致,导致重复处理;

按照需求,如果对可用性要求高,可以忽略重复处理;如果对准确性要求高,可以等待

4.3.3 最少同步副本

min.insync.replicas

4.4 在可靠的系统里使用生产者

4.4.1 发送确认

acks的配置

4.4.2 配置生产者的重试参数

错误分类
根据生产者是否需要处理,分为:生产者可以自动处理的错+需要开发者手动处理的错误;
根据重试与否,分为可重试错误和不可重试错误;

LEADER_NOT_AVAILABLE是一个可重试错误,可以重发信息直到leader接收;而invalid_config,是配置错误,重试也没办法解决问题,故,不可重试错误

不丢失任何信息,就需要重试错误多重试;虽然可能会导致信息重复;比如张三手机信号不好,一开始转账的1000e转圈圈,北京认为网络故障,肯定转账失败,又转了1000e,结果信号好了,2000e转过去了,就尴尬了
当然,有些信息重复了也没关系,有些信息不能重复

4.4.3 额外的错误处理

不可重试的 broker 错误,例如消息大小错误、认证错误等;
在消息发送之前发生的错误,例如序列化错误;
在生产者达到重试次数上限时或者在消息占用的内存达到上限时发生的错误

4.5 在可靠的系统里使用消费者

现在,李世民和要从北京城六区提取1000e打击游牧,按照顺序,应该是预算的10000e-11000e;10000e是此时的偏移;正常情况下,李世民管城六区的15000e,李隆基管郊区的20000e,共计35000e;现在加入李隆基由于安史之乱被迫退位;李世民接管郊区的20000e,那么首先,需要直到李隆基花了多少钱,不然超支了就不好了;所以李隆基退位前要高速李世民,现在郊区还剩下1000e给你挥霍;李世民虽然不爽,但是没办法,只剩这么多了,凑合过吧

这个1000e就是已经提交的偏移量

如果李隆基退位前申请了1000e给杨贵妃开party,但是没能花完就被迫退位,这些消息就没办法给李世民了,因为已经给李隆基了,没办法吐出来;这些钱只能给杨贵妃了,追不回来了;
这1000e,是已提交信息

因此要重视偏移量提交的时间的和提交的方式;如果李世民赶在李隆基提1000e前让李隆基提交偏移量,那么就能省下1000e,还剩2000e了.

3.5.1 消费者的可靠性配置

第 1 个是 group.id;如果两个消费者具有相同的group.id,并且订阅了同一个主题,那么每个消费者会分到主题分区的一个子集,也就是说它们只能读到所有消息的一个子集.

第 2 个是 auto.offset.reset 这个参数指定了在没有偏移量可提交时(比如消费者第 1 次启动时)或者请求的偏移量在 broker 上不存在时,消费者干嘛.
earlist,从分区开始位置读取数据;会导致大量重复.
latest,从分区末尾位置读取数据,可能错过一些消息.

第 3 个是 enable.auto.commit 可以让消费者基于任务调度自动提交偏移量,也可以在代码里手动提交偏移量.

第 4 个是 auto.commit.interval.ms 自动提交偏移量,可以通过该参数配置提交的频度,默认值是每 5 秒钟提交一次.

3.5.2 显示提交偏移量

如何提交偏移量?如何更好地开发具有可靠的消费者应用程序?

1, 总是在处理完事件后再提交偏移量
2, 提交频度是性能和重复消息数量之间的权衡;提交频繁,会提高性能,但可能导致重复消息;提交低频,性能较差,但是不会重复信息
3, 确保对提交的偏移量心里有数
4, 再均衡
5, 消费者可能需要重试
6, 消费者可能需要维护状态
7, 长时间处理:用线程池来处理,多线程,并行处理,加快速度
8, 仅一次传递: Kafka 里的每个消息只被写到外部系统一次;

实现仅一次处理的最简单方法:把结果写入一个支持唯一键的系统里,这样可以避免重复,重复数据会被覆盖或者写不进去

3.6 验证系统可靠性

配置验证、应用程序验证以及生产环境的应用程序监控

3.6.1 配置验证

验证配置是否满足你的需求.
帮助你理解系统的行为,了解系统的真正行为是什么
两个工具:org.apache.kafka.tools 包里的 Verifiable Producer 和 VerifiableConsumer 这两个类
首领选举,控制器选举,重启,不完全首领选举测试等

3.6.2 应用程序验证:应用程序是否满足需求
3.6.3 在生产环境监控可靠性

对于消费者来说,最重要的指标是 consumer-lag,该指标表明了消费者的处理速度与最近提交到分区里的偏移量之间还有多少差距.理想情况下,该指标总是为 0,消费者总能读到最新的消息.

++++++++++++++++++++++++++++++++分割线++++++++++++++++++++++++++++++++
关于Kafka权威指南的学习,先告一段落,后续的章节,我目前还没用到,短期应该不太会学习.未来如果用到,也一定会更新的.

想看第一篇的,见Kafka 笔记01.
参考资料
[1]: https://www.cnblogs.com/oneLittleStar/p/13528835.html
[2]:《Kafka权威指南》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值