这两天重点学习了下kafka消息队列,对其相关比较重要的问题进行总结。(以下内容均个人理解总结,不对的地方多多指正)
1.kafka组成有哪些?
Broker:kafka保存消息的中转站,集群中包含多个kafka服务节点,每个kafka服务节点就称为broker。
Topic:主题,用来存储不同类别的消息。
Partition:分区队列,一个Topic包个或多个Partition,在创建Topic时指定包含的Partition数量,kafka的有序性就是通过分区来实现,分区内是有序的。
Replication:副本,一个分区对应有多个副本,分布在不同的Broker上,副本的数量不会大于broker的数量,一个副本作为Leader,所有的读写请求都会通过Leader完成,Follower只负责备份数据所有Follower会自动的从Leader中复制数据,当Leader宕机后, 会从Follower中选出一个新的Leader继续提供服务,实现故障自动转移。
Message:消息,是通信的基本单位。
Producer:消息的生产者,向Kafka的一个topic发布消息,可以指定向某个分区发送消息。
Consumer:消息的消费者,订阅topic并消费其发布的消息。
Consumer Group:每个消费者都属于一个特定的Consumer Group,消费者组之间可以重复消费,消费组内部则只能由某一个具体的消费者消费。
Zookeeper:协调kafka的正常运行,集群等,保存一些元数据信息,kafka不能脱离zk单独运行。
2.如何确保消息队列消息不丢失?
kafka的ack有是三个选项,分别是0,1,-1,可以通过属性来配置,0表示不进行消息接收是否成功的确认,1表示当leader副本接收成功后,返回接收成功确认信息,-1表示当leader和follower都接收成功后,返回确认信息。
消息从发送到消费的整个流程中,主要涉及三个阶段,生产阶段,和消费阶段。
在生产阶段,需要我们去捕获消息的错误,并重发消息。
在存储阶段,要确保不会因为broker的宕机而使消息丢失,所以需要配置好相关的刷盘和复制参数。
在消费阶段,需要在完成业务逻辑之后,在发送确认的ack给broker。
3.消息幂等性以及避免重复消息
针对消息重复,一般有三种标准,at most once,at least once,exactly once ,大部分消息队列支持的是at least once+幂等性操作。所谓幂等性就是f(f(x))=f(x),也就是说一个服务不管调用多少次,只要入参一样,与调用一次的结果都是一样的。比如说,将id=10的账号,金额更新为10,那么不管执行几次这个操作,结果都是一样的,所以也无需关注重复消息,但是如果将id=10的账号金额+10,那么这个操作就不是幂等了,这时候的解决思路就是要防重,通常有,数据库唯一索引防重,前置条件防重,增加版本号防重。
4.如何用消息队列实现分布式事务?
分布式事务一般的方法2PC(两阶段提交),这边主要说明下消息队列实现的分布式事务。假设现在有两个系统,一个是订单系统,一个是用户系统,当用户下单成功后,去更新用户系统中的已购买到的商品,那这个操作是具有事务性的,要么一起成功,要么一起失败。所以当用户下单的时候首先开启一个事务,然后发送一个“半消息”给消息队列broker,这个半消息对消费者而言是不可见的,然后进行本地的事务,创建订单,等本地事务完成后,如果订单创建成功,则提交事务消息,消费者,也就是用户系统去消费,进行更新已购买的商品,如果订单创建失败,那么事务消息回滚,这样用户系统不会收到消息,这样就实现了基于消息队里的分布式事务。
5.kafka如何保证消费顺序?
kafka发送消息的时候,可以指定向具体的某个分区发送消息,在分区中就是个顺序队列,而消费者只会消费固定分区中的消息,所以在分区中一定是有序的。
6.ISR是什么?HW和LEO又是什么?
ISR:表示的是跟leader副本同步的“差不多”的follwer副本列表,这个差不多是有一个阈值来控制的,比如follwer中有一个机器宕机了,他与leader之间的同步时间相差超过了这个阈值,那么这个机器就会被踢出ISR列表。不过等到它恢复,还是继续会与leader同步,等同步到差不多的时候,又会重新加入到ISR列表中。
HW:即表示高水位,就是已经备份到的消息的位置。
LEO:日志偏移位置,即每个分区中的offset,即下次读写的位置。
7.消息积压如何处理?
设计系统的时候有一个原则就是一定要保证消费端的消费性能要高于生产端的发送性能。导致消息积压,最直接的原因,就是两种,一是发送变快了,二是消费变慢了。最直接的办法就是水平扩容consumer的数量,同时还要增加分区数量。有时候还要排查是否是消费端某个消息消费失败,导致重复消费,导致积压。对消息积压还可以做好预防处理,提升生产者和消费者的性能,比如在生产者这边使用多线程并发,充分利用好消息队列的优势,在消费者水平扩容。
8.kafka支不支持读写分离
不支持,kafka的生产与消费消息都是与leader副本进行交互,follwer副本只是备份数据,如果支持主写从读的读写分离,那么会daoz导致2个问题:① 数据一致的问题,leader副本与follwer副本之间的同步会有延时,这样会导致数据的不一致。②延时问题,kafka的主从同步比redis这些缓存更加耗时,对于延时敏感的应用,主写从读并不合适。
9.kafka的分区分配策略
实质上每个消费者消费的分区都是固定的,当增加消费者,或者增加分区的时候就会触发rebalance。
range:有两个参数,n=分区数/消费者数量,m=分区数%消费者数量,这个策略的主要思想就是前m个消费者,分配n+1个分区。
roundrobin:将分区按照hashcode进行排序,轮训分发给每个消费者。
sticky:初始分配大致与roundrobin类似,当有消费者脱离消费组的时候,那么就会全部重新轮训分配,而roundrobin则是保证原有的分配逻辑,将脱离的消费者消费的分区进行轮训分配。保证一种均匀分配的策略。
来源:CSDN
作者:王小锤DW3
链接:https://blog.csdn.net/qq_21996541/article/details/104258993