ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

浅析Kafka面试题-元一软件

浅析Kafka面试题-元一软件 1浅析消息队列面经这里我们通过讲解一些常见的面试题和其变种的问法来熟悉消息队列中的一些核心的概念然后深挖其中知识点以此来进行拓展在这个文档中最好只是做简单但确的总结性质的语言来讲述其他完整的回答根据相应的模块整理起来即可1.1消息队列应用场景为什么使用消息队列使用消息队列有哪些好处和坏处消息队列的优缺点1.2常见的消息队列有哪些以及他们的对比MQ的技术选型1.3消息模型有哪些1.4MQ框架是如何实现高吞吐量的2.1如何解决MQ的消息丢失2.2如何解决消息的重复消费ExactlyOnce语义消息的幂等性重复出现的原因是什么2.3如何保证MQ的消息是有序的3如果出现消息积压应该怎么办4如何保证数据的一致性问题5事务消息是如何实现的6MQ框架如何做到高可用(1),消息队列应用场景消息队列中的一些其他的特点等信息需要查看另外的文档做了详细的整理。异步处理将一个请求链路中的非核心流程拆分出来异步处理减少主流程链路的处理逻辑提升吞吐量。限流消峰可以通过消息队列长度控制请求量可以缓解短时间内的高并发请求。广泛应用于秒杀或抢购活动中避免某一刻流量过导致应用系统挂掉的情况应用解耦多应用通过消息队列对同一消息进行处理避免调用接口失败导致整个过程失败消息通讯消息队列中内置了高效的通信机制因此也可以用在纯的消息通讯。比如实现点对点消息队列或者聊天室等。日志处理解决大量的日志传输(2),常见的几种消息队列以及技术选型?常见的消息队列RabbitMQKafkaRocketMQ… …技术选型主要可以通过以下几个维度当前系统中主要技术栈以及团队中对哪个框架更加熟悉数据的吞吐量(Kafka)对事务支持性(RabbitMQ)社区的活跃程度… …(3),如何解决消息的重复消费1首先分析消息队列本身都是保证的至少一次(At least Once)的语义所以如果要通过MQServer配置和业务代码配合来解决。另外其他几种常见的语义我们需要保证Exactly Once语义。最多一次At most once至少一次At least once仅一次 Exactly once2分析出现重复消费原因(1)生产者发送了重复的消息一般为了保证消息的可靠性生产者在发送了信息后需要等待Broker的响应此时如果出现网络波动等情况响应超出了时间之后会导致数据的重复发送(2)消费者在消费消息的重复的当消费者在消费消息的时候虽然基本的业务逻辑已经走完了但是在提交Offset的时候消费者服务挂了那么这条被消费但是没有被提交的消息会发送到其他消费者中导致这条消息被重复消费。(3)补充“幂等性”的概念通俗的说同样的接口或者数据去调用同一个接口的时候无论重复调用多少次总能保证数据的正确性不能出错这里特指的是接口的幂等性。3解决重复的消费的问题(1),基于业务侧的调整生产者可以在发送消息的时候添加一个唯一的字段在插入数据的时候在数据库中进行唯一校验即可但是这样在一定的程度上会影响数据库的性能一般是需要强检验的场景中会使用。消费者首先是开始手动提交Offset单独创建一个消费记录表将提交Offset、执行插入动作的sql和插入消费记录表唯一key的操作都放在同一个事务中那么当插入之前先判断这个唯一的key是否已经在消费记录表中只有不存在的才继续消费。(4),如果出现消息积压应该怎么办1分析出现消息积压一般是是消息的消费速度比不上生产的速度从而导致了消息堆积。(1),导致出现消息积压的情况可能有以下集中情况磁盘写满了导致数据写入磁盘的时候无法写入进而导致的消息的积压。数据写入MySQL但是此时MySQL的服务出现了异常也可能直接服务down掉等等导致的消息积压。有可能是因为程序中某步操作时时候线程耗时过长导致的消息堆积2解决方法消费者(1),可以适当增加消费者组的机器数量以提升整体的消费能力如果是线上的紧急任务我们可以通过创建一个TopicPartition是原来的十倍然后临时写一个Consumer程序并启动多个线程去进行消费消费的数据只是临时存储等待处理消费完积压的数据之后恢复原先部署的架构重新用原先Consumer机器来消费消息。如果可以的话尽量保留部分现场环境便于排查消费能力下降的原因。(2),排查出问题之后我们不仅要解决问题也要对集群的消费能力再进行一次评估避免是因为消费能力不够引起的消息堆积尤其是针对一些顺发的流量比如大促活动之类的。(3),优化每条消息的消费过程从业务的角度考虑优化。生产者生产者要能及时感知到消费者的能力不足出现消息积压的时候可以适当放缓消息放入的速度可以直接给前端页面提示排队等等。3补充数据积压的时间太长了导致是消息队列中设置了过期时间的的数据丢失问题答如果出现消息的丢失问题想办法找到丢失的部分数据重新发送到MQ集群里。(5),如何保证数据的一致性问题关于数据的一致性问题这里通过“解耦”场景举例比如电商场景中下单成功之后再通知库房扣减库存。那么这个时候我们在同一个事务空间中先处理下单的数据库操作然后发送MQ消息剩下的扣减库存的操作交给消费者进行。另外在消费的环节也可能会出现数据不一致的情况那么我们可以采用最终一致性原则增加重试的机制。(6),MQ框架是如何实现高吞吐量的消息可以批量处理对消息体进行压缩从而节省传输的带宽和存储空间顺序写入磁盘(Kafka)每个分区内是有序的。零拷贝(Kafka)直接在内核层将消息的内容传递给网络Socket从而避免了应用层之间的拷贝。采用页缓存(Page Cache)使用操作的系统的内存而不是使用JVM的内存能够避免占用堆内存和GC问题。采用分区的设计在每个分区中保持是有序的另外每个分区可以针对不同的机器消费信息可以用于并发处理。(7),MQ事务消息是如何实现的这里的实现方式类似于“两阶段提交”在MySQL的事务中也是处理的。2浅析Kafka面试题(1),Kafka为什么不支持读写分离如果使用读写分离的策略必然会有主和副本之间数据同步要保证其一致性另外副本在同步的时候如何保证实时性。数据一致性如果采用一主多从的方式Leader副本的数据在同步到Follower副本的时候会存在一定的延迟那么Follower副本的消息位移也不一样但是消费者需要通过消费位移来控制消息拉取的进度多个副本之间要维护统一消费位移的一致性。那么如果要解决这个问题就需要引入分布式锁保证锁的安全非常耗费性能。实时性如果网络延迟比较大在同步的过程中难免会影响效率从而可能无法满足实时性业务的需求。(2),MQ如何实现高可用这里直接以Kafka举例的其他基本是类似的。简单来说就是几个节点之间选举出主节点(Leader)那么这个时候如果主节点宕机了可以从其他的节点中进行重新选举。另外每个节点在保存的数据的时候会在从节点(Follower)中保存相应的副本通过多副本机制又是另一个高可用的体现。(3),如何保证MQ的消息是有序的这里的讲解主要是以Kafka为例进行讲解的。方式1可以强制只有一个分区那么在一个分区中就是有序的那么整体就是有序的。但是只有一个分区kafka的吞吐量就不高了。方式2从业务的角度考虑可以通过自定义分区的策略(org.apache.kafka.clients.Partitioner)将满足指定规则的数据存储在同一个分区中从而实现有序(1),比如同一个订单的不同状态的消息存储在同一个分区中(2),或者同一个登录的用户的各类操作存储在同一个分区中(4),如何解决MQ的消息丢失这里是针对Kafka进行分析的其他的框架也会有类似的1分析可能出现消息丢失的几种情况(1)消息队列本身在写数据的过程中我们如果只保证写入Leader节点而不管副本是否同步成功就算写入成功的话这种情况下是存在单点故障的即如果Leader节点挂了那么就会出现丢失数据的情况(2)生产者由于网络的延迟导致数据出现发送失败情况也可以理解为数据丢失的一种情况(3)消费者使用自动提交Offset的方式会出现数据在处理完成之前就把Offset提交了这样也会出现数据丢失的情况2针对以上几种情况提出具体的解决方案生产者(1),配置acks1 或者 acksall参数在Leader节点写入成功之后将消息同步到副本列表中(2),数据发送失败了之后可以指定重试(retries)的次数在一些强校验的场景下可以设置为Integer.MAX_VALUE可以从Broker的角度考虑保证消费者消费到数据之后再删除Broker中的暂存的信息。如果是kafka的话在Broker层面使用到了ISR列表 HW高水位 Leader Epoch来防止数据丢失。消费者端关闭自动提交根据回调函数合理处理消息并手动提交Offset。(5),补充一些常见的面试题这里主要是题目描述一下然后简答写一些回答的关键字。墙裂推荐大家仔细阅读并可以关注其公众号。从面试角度一文学完 Kafka1),什么是分布式消息中间件简单说是一个消息流的管道。2),消息中间件的作用是什么解耦、异步、削峰。3),消息中间件的使用场景是什么除了上述笼统的说法从实际的业务中描述的话可以用在一些秒杀的场景中、两个系统的耦合性太高的话可以去做拆分。4),消息中间件选型主要看业务场景是追求数据的可靠性(事务)还是追求吞吐量。5),简单讲下 Kafka 的架构生产者 -- Broker集群(Topic、Partition(Leader、Follower)、Zookeeper集群) -- 消费者6),Kafka 中 Zookeeper 的作用起到一个注册中心的作用其本身也是一个分布式的集群管理工具主要的作用便是管理集群、负责Leader节点的选举Zookeeper是怎么作用Leader选举的类似与FIFO也就是先到先得另外如果主节点挂掉了之后会从Follower节点中重新进行一轮筛选。了不了解Zab协议原子·崩溃协议其中的原子是指原子广播协议用来保证Server之间的同步从而保证数据的一致性崩溃是指支持崩溃恢复即如果出现服务器宕机重启之后重新选举主节点同时Follower节点与Leader节点的同步来完成崩溃恢复。Zookeeper存储方式基于ACL的策略控制方式实现树状的存储另外他是存储在内存中并以此来保证高吞吐和低延迟。7),Kafka 是推模式还是拉模式推拉的区别是什么生产者是推模式消费者是拉模式区别的话主要就是一个主动拉取数据另一个是被动接收数据把通过主动拉取数据的方式可以自己管理消费的Offset从而提高可控性和读取的性能。8),Kafka的Offset是什么这里的Offset即消息的位移或者说是偏移量其本质上是有两种含义一是Broker当中最新消息的Offset的值二是消费者消费到了哪一条的数的Offset的值。9),Kafka 如何广播消息广播是指发送消息给所有的消费者也就是消费者组的概念。同一条消息只能被同一个消费者组中一个消费者消费但是可以被多个消费者组同时消费。10),Kafka 的消息是否是有序的Topic是无序的但是每个分区内是有序的。11),Kafka 是否支持读写分离不支持所有的读写操作都在Leader节点上Follower节点做镜像节点负责同步和备份数据当主节点Down掉后会从Follower节点中重新选举主节点从而实现HA12),Kafka 如何保证高可用高可用体现在集群的高可用和数据的高可用两个方面集群的高可用体现Leader节点在Down之后可以重新从Follower节点中重新选择数据的高可用体现在“多副本机制”、“ISR列表”、“HW”、“Leader Epoch”通过配置acksall实现多个副本都复制成功的时候才算数据接收成功ISR列表指的是达到数据同步标准的Follower节点HW是High Water Mark 高水位防止消费者读到未同步的数据Leader Epoch 是解决的HW错位导致的数据不一致的问题1Epoch是一个单调递增的版本号2Start Offset是我们下一次需要从哪开始访问的位移13),是否支持事务在0.11之后是支持事务的。14),分区数是否可以减少不能啊会导致数据丢失。15),Kafka 有哪些命令行工具你用过哪些/bin 目录下的脚本文件管理 kafka 集群、管理 topic、模拟生产者和消费者等等16),Kafka Producer 的执行过程1Producer生产消息 -- 2从Zookeeper找到Partition的Leader -- 3推送消息 -- 4通过ISR列表通知给Follower -- 5 Follower从Leader拉取消息并发送ack -- 6Leader收到所有副本的ack更新Offset并向Producer发送ack表示消息写入成功。17),Kafka Producer 有哪些常见配置acks的配置(acksall)、异常重试的配置(retries)、提升消息吞吐量(设置缓冲区的大小、开启消息压缩compression.typ)的配置18),如何让 Kafka 的消息有序Kafka 在 Topic 级别本身是无序的只有 partition 上才有序所以为了保证处理顺序可以自定义分区器将需顺序处理的数据发送到同19),一个 Partition Producer 如何保证数据发送不丢失ack机制(acksall)重试机制20),如何提升 Producer 的性能批量异步压缩21),如果同一 group 下 consumer 的数量大于 part 的数量kafka 如何处理多余的 consumer 将处于无用状态不消费数据。22),Kafka Consumer 是否是线程安全的不安全所以在Consumer端采用的是 单线程消费多线程处理23),讲一下你使用 Kafka Consumer 消费消息时的线程模型为何如此设计Thread-Per-Consumer Model这种多线程模型是利用Kafka的topic分多个partition的机制来实现并行每个线程都有自己的consumer实例负责消费若干个partition。各个线程之间是完全独立的不涉及任何线程同步和通信所以实现起来非常简单。其他的详细信息可以看上述连接24),Kafka Consumer 的常见配置心跳时间的配置、一次Poll返回数据的最大条数、是否自动提交位移 等等25),Consumer 什么时候会被踢出集群崩溃网络异常处理时间过长提交位移超时26),当有 Consumer 加入或退出时Kafka 会作何反应进行 Rebalance27),什么是 Rebalance何时会发生 Rebalance组成员发生变化订阅的主题发生变更定于主题的分区数发生变更28),Kafka 的交付语义at most once最多一次即不会产生重复数据但可能会丢数据at least once至少一次即可能会产生重复数据但不会丢数据exactly once准确的一次不多也不少29),Replic 的作用通过Replic(副本)来保证数据的高可用性30),为什么 Follower 副本不提供读服务这个问题本质上来说是对性能和一致性的取舍。假设follower也提供读写服务固然会提高性能但是同时也会出现类似于数据库中幻读、脏读等问题。出现这一情况主要是因为他们之间的同步的不一定是完全一致的。31),Leader 和 Follower 是什么Partition分区中分为两种节点Leader、Follower这两者之间是主备关系当Leader节点挂了的时候会通过选择在Follower节点中生成新的Leader节点。Leader所有的读写操作都发生在Leader分区上。Follower所有的Follower节点都需要从Leader节点上同步消息并做为Leader的备份节点。32),什么是 ARISRARAll Replication所有分配的副本列表ISRIn-Sync Replication管理的Follower副本同步的列表我们会配置一个可容忍的延迟数量只有大于等于这个数量的Follower才会进入到ISR列表中同时如果Leader节点挂掉之后会从ISR列表中重新选举新的Leader。33),Kafka 中的LSO、LEO、LW、HW等分别代表什么LSO是log Start Offset表示第一消息的offsetLEO是Log End Offset日志末端位移的概念指的是每个副本最后一个 offset 1LW是Low Watermark的缩写俗称“低水位”代表AR集合中最小的logStartOffset值HW是High Watermark的缩写俗称“高水位”指的是消费者能见到的最大的 offsetISR 列表中最小的 LEO。35),Kafka 为保证优越的性能做了哪些处理Partition并发顺序读写磁盘每个分区文件在本地实行分段(Segment)存储每个段都采用append追加的方式存储。零拷贝是指减少了一次数据从内核区到用户缓冲区的拷贝。PageCache页缓存批量读写消息压缩3餐饮系统消息队列应用专题分析本部分的整理内容是来自《苏三说技术-我用kafka两年踩过的非比寻常的坑》墙裂推荐大家仔细阅读并可以关注其公众号。1保证消息的顺序性这里一个订单的不同状态举例说明比如“下单” - “支付” - “完成” - “撤销”等需要保证不能出现“下单”的消息还没有读到就先读到“支付”或者“撤销”的消息吧所以是有必要保证消息的有序性的。**实际处理**通过每一个订单编号路由到同一个Partition分区中然后部署相同分区数的消费者节点从而一个分区对应一个消费者节点从而保证同一个订单的不同状态的消息是有序的。2虽然写入同一个分区是可以保证有序的但是如果出现网络超时的情况导致“下单”的消息一直没有发送成功但是收到了“支付”的订单消息那么这个时候一来消息是错乱的二是没有下单信息页面中无法显示完整的消息。实际处理基础的想法是采用重试的机制(1),同步重试在消费信息的时候出现网络失败等情况立马重试3~5次但是这样会严重的影响消费者的消费速度降低他的吞吐量。(2),异步重试将失败的消息保存在重试表中然后有个定时任务不断的拉取重试Todo:1这里是需要补充重试表得设计规则以及相关数据是如何保存的是否需要放置在同一个事务中处理。2关于一些常见重试的实际编程比如spring-retry的使用3关于elastic-job的使用消费者在处理消息的时候首先判断当前的订单号是否在重试表中如果存在则执行将当前消息保存在重试表中如果没有再正常进行业务处理当出现了异常的时候才把消息保存在重试表中。**补充**另外博文中提到后来使用用elastic-job建立了 失败重试机制 如果重试了 7 次后还是失败则将该消息的状态标记为 失败 发邮件通知开发人员。3处理消息积压的问题在业务中将消息积压的问题体现很明显后台厨房可能很长一段时间看不到客户下的单据就会导致餐品上的不及时。(1),从磁盘网络传输的角度出发消息在传输的过程中如果消息体的内容过多导致消息的多无论是在网络的传输还是数据落地到磁盘再从磁盘中获取这两个方面考虑效率都是低下的。实际处理1),订单系统发送的消息中只包含订单id、状态等关键的信息。2),后厨显示系统在消费到信息之后通过id去查询订单系统对应的相信数据存在两个服务之间的远程调用。3),后厨系统中判断数据库是否有该订单的数据如果有则更新没有则直接入库同时可以避免出现消息重复消费的情况。(2),注意检查路由规则设计是否合理(3),对于高并发的设计要合理的使用线程池(4),对于单表的数据量如果过大可以根据实际的情况进行分表处理即可。4数据库的主从复制最常见的方式就是在发现处从复制的有一定的延迟的时候通知DBA进行处理同时业务数据在查询不到结果的时候将对应的查询id落地到重试表中进行相关的重试操作。5数据的重复消费问题在当前场景下是在插入保存的时候需要保证是幂等的。于是可以在保存数据的时候使用insert into ... on duplicate key update控制存在的时候更新不存在的时候插入。
返回列表