​前言

在本文开始之前,作者一直有个疑惑,就是面试题是只写写问题和答案就草草了事,还是应该深入分析一下其背后发生的一些原理。和朋友探讨以后作者还是决定采用后者的方式,因为我认为不仅要做到知其一,更要知其二,所以我们就用讲解原理的方式来看看 Kafka 常见的面试题吧。另外避免文章过长,我打算接下来使用几篇文章来详解每道题背后的原理。好了废话有点多,直接开干。

文章概览

  • kafka 如何保证数据的可靠性和一致性?
  • kafka 为什么那么快?
  • Kafka 中的消息是否会丢失和重复消费?
  • 为什么要使用 kafka,为什么要使用消息队列?
  • 为什么 Kafka 不支持读写分离?

kafka 如何保证系统的高可用、数据的可靠性和数据的一致性的?

kafka 的高可用性:

  1. Kafka 本身是一个分布式系统,同时采用了 Zookeeper 存储元数据信息,提高了系统的高可用性。
  2. Kafka 使用多副本机制,当状态为 Leader 的 Partition 对应的 Broker 宕机或者网络异常时,Kafka 会通过选举机制从对应的 Replica 列表中重新选举出一个 Replica 当做 Leader,从而继续对外提供读写服务(当然,需要注意的一点是,在新版本的 Kafka 中,Replica 也可以对外提供读请求了),利用多副本机制在一定程度上提高了系统的容错性,从而提升了系统的高可用。

Kafka 的可靠性:

  1. 从 Producer 端来看,可靠性是指生产的消息能够正常的被存储到 Partition 上且消息不会丢失。Kafka 通过 request.required.acks和min.insync.replicas 两个参数配合,在一定程度上保证消息不会丢失。
  2. request.required.acks 可设置为 1、0、-1 三种情况。
request.required.acks=1

设置为 1 时代表当 Leader 状态的 Partition 接收到消息并持久化时就认为消息发送成功,如果 ISR 列表的 Replica 还没来得及同步消息,Leader 状态的 Partition 对应的 Broker 宕机,则消息有可能丢失。

request.required.acks=0

设置为 0 时代表 Producer 发送消息后就认为成功,消息有可能丢失。

request.required.acks=-1

设置为-1 时,代表 ISR 列表中的所有 Replica 将消息同步完成后才认为消息发送成功;但是如果只存在主 Partition 的时候,Broker 异常时同样会导致消息丢失。所以此时就需要min.insync.replicas参数的配合,该参数需要设定值大于等于 2,当 Partition 的个数小于设定的值时,Producer 发送消息会直接报错。

上面这个过程看似已经很完美了,但是假设如果消息在同步到部分从 Partition 上时,主 Partition 宕机,此时消息会重传,虽然消息不会丢失,但是会造成同一条消息会存储多次。在新版本中 Kafka 提出了幂等性的概念,通过给每条消息设置一个唯一 ID,并且该 ID 可以唯一映射到 Partition 的一个固定位置,从而避免消息重复存储的问题(作者到目前还没有使用过该特性,感兴趣的朋友可以自行在深入研究一下)。

Kafka 的一致性:

  1. 从 Consumer 端来看,同一条消息在多个 Partition 上读取到的消息是一直的,Kafka 通过引入 HW(High Water)来实现这一特性。
消息同步图

从上图可以看出,假设 Consumer 从主 Partition1 上消费消息,由于 Kafka 规定只允许消费 HW 之前的消息,所以最多消费到 Message2。假设当 Partition1 异常后,Partition2 被选举为 Leader,此时依旧可以从 Partition2 上读取到 Message2。其实 HW 的意思利用了木桶效应,始终保持最短板的那个位置。

从上面我们也可以看出,使用 HW 特性后会使得消息只有被所有副本同步后才能被消费,所以在一定程度上降低了消费端的性能,可以通过设置replica.lag.time.max.ms参数来保证消息同步的最大时间。

kafka 为什么那么快?

kafka 使用了顺序写入和“零拷贝”技术,来达到每秒钟 200w(Apache 官方给出的数据) 的磁盘数据写入量,另外 Kafka 通过压缩数据,降低 I/O 的负担。

  1. 顺序写入

大家都知道,对于磁盘而已,如果是随机写入数据的话,每次数据在写入时要先进行寻址操作,该操作是通过移动磁头完成的,极其耗费时间,而顺序读写就能够避免该操作。

  1. “零拷贝”技术
普通数据拷贝流程图

普通的数据拷贝流程如上图所示,数据由磁盘 copy 到内核态,然后在拷贝到用户态,然后再由用户态拷贝到 socket,然后由 socket 协议引擎,最后由协议引擎将数据发送到网络中。

"零拷贝"流程图

采用了“零拷贝”技术后可以看出,数据不在经过用户态传输,而是直接在内核态完成操作,减少了两次 copy 操作。从而大大提高了数据传输速度。

  1. 压缩

Kafka 官方提供了多种压缩协议,包括 gzip、snappy、lz4 等等,从而降低了数据传输的成本。

Kafka 中的消息是否会丢失和重复消费?

  1. Kafka 是否会丢消息,答案相信仔细看过前面两个问题的同学都比较清楚了,这里就不在赘述了。
  2. 在低版本中,比如作者公司在使用的 Kafka0.8 版本中,还没有幂等性的特性的时候,消息有可能会重复被存储到 Kafka 上(原因见上一个问题的),在这种情况下消息肯定是会被重复消费的。

这里给大家一个解决重复消费的思路,作者公司使用了 Redis 记录了被消费的 key,并设置了过期时间,在 key 还没有过期内,对于同一个 key 的消息全部当做重复消息直接抛弃掉。 在网上看到过另外一种解决方案,使用 HDFS 存储被消费过的消息,是否具有可行性存疑(需要读者朋友自行探索),读者朋友们可以根据自己的实际情况选择相应的策略,如果朋友们还有其他比较好的方案,欢迎留言交流。

为什么要使用 kafka,为什么要使用消息队列?

先来说说为什么要使用消息队列?

这道题比较主观一些(自认为没有网上其他文章写得话,轻喷),但是都相信大家使用消息队列无非就是为了 解耦异步消峰

系统调用图

随着业务的发展,相信有不少朋友公司遇到过如上图所示的情况,系统 A 处理的结构被 B、C、D 系统所依赖,当新增系统 E 时,也需要系统 A 配合进行联调和上线等操作;还有当系统 A 发生变更时同样需要告知 B、C、D、E 系统需要同步升级改造。

引入消息队列图

引入消息队列后有两个好处:

  1. 各个系统进行了解耦,从上图也可以看出,当系统 A 突然发生热点事件时,同一时间产生大量结果,MQ 充当了消息暂存的效果,防止 B、C、D、E 系统也跟着崩溃。
  2. 当新系统 E 需要接入系统 A 的数据,只需要和 MQ 对接就可以了,从而避免了与系统 A 的调试上线等操作。

引入消息队列的坏处:

万事皆具备两面性,看似引入消息队列这件事情很美好,但是同时也增加了系统的复杂度、系统的维护成本提高(如果 MQ 挂了怎么办)、引入了一致性等等问题需要去解决。

为什么要使用 Kafka?

作者认为采用 Kafka 的原因有如下几点:

  1. Kafka 目前在业界被广泛使用,社区活跃度高,版本更新迭代速度也快。
  2. Kafka 的生产者和消费者都用 Java 语言进行了重写,在一定程度降低了系统的维护成本(作者的主观意见,因为当下 Java 的使用群体相当庞大)。
  3. Kafka 系统的吞吐量高,达到了每秒 10w 级别的处理速度。
  4. Kafka 可以和很多当下优秀的大数据组件进行集成,包括 Spark、Flink、Flume、Storm 等等。

为什么 Kafka 不支持读写分离?

这个问题有个先决条件,我们只讨论 Kafka0.9 版本的情况。对于高版本,从 Partition 也可以承担读请求了,这里不多赘述。

Kafka 如果支持读写分离的话,有如下几个问题。

  1. 系统设计的复杂度会比较大,当然这个比较牵强,毕竟高版本的 Kafka 已经实现了。

2. 从上图可以看出,从从 Partition 上读取数据会有两个问题。一、数据从主 Partition 上同步到从 Partition 有数据延迟问题,因为数据从生产到消费会经历 3 次网络传输才能够被消费,对于时效性要求比较高的场景本身就不适合了。二、数据一致性问题,假设主 Partition 将数据第一次修改成了 A,然后又将该数据修改成了 B,由于从主 Partition 同步到从 Partition 会有延迟问题,所以也就会产生数据一致性问题。

分析得出,通过解决以上问题来换取从 Partition 承担读请求,成本可想而知,而且对于写入压力大,读取压力小的场景,本身也就没有什么意义了。

总结

本文介绍了几个常见的 Kafka 的面试题,下篇文章我们分析一下延迟队列及其实际落地场景的使用问题,敬请期待


历史精彩文章推荐:

Kafka系列第7篇:你必须要知道集群内部工作原理的一些事!​mp.weixin.qq.com

Kafka系列第6篇:消息是如何在服务端存储与读取的,你真的知道吗?​mp.weixin.qq.com

kafka系列第5篇:一文读懂消费者背后的那点"猫腻"​mp.weixin.qq.com

Kafka系列第4篇:消息发送时,网络“偷偷”帮忙做的那点事儿​mp.weixin.qq.com

重要:Kafka第3篇之一条消息如何被存储到Broker上​mp.weixin.qq.com

文章参考:

https://www.cnblogs.com/binyue/p/10308754.html

https://www.cnblogs.com/yoke/p/11477167.html

微信公众号搜索【z小赵】,更多系列精彩文章等你解

对接kafka_Kafka系列9:面试题是否有必要深入了解其背后的原理?我觉得应该刨根究底(上)...相关推荐

  1. Kafka系列10:面试题是否有必要深入了解其背后的原理?我觉得应该刨根究底(下)...

    前言 在今天文章开始之前,想和粉丝朋友们先分享一个好消息,作者坚持以原创的态度去努力写好每一篇文章,同时得到了一小部分粉丝朋友们的认可和 InfoQ 写作平台的支持.在此非常感谢粉丝朋友的支持,同时也 ...

  2. 面试官系统精讲Java源码及大厂真题 - 34 只求问倒:连环相扣系列锁面试题

    34 只求问倒:连环相扣系列锁面试题 自信和希望是青年的特权. 引导语 面试中,问锁主要是两方面:锁的日常使用场景 + 锁原理,锁的日常使用场景主要考察对锁 API 的使用熟练度,看看你是否真的使用过 ...

  3. 大厂经典面试系列之三:唯品会大数据开发面试【建议关注收藏订阅,你早晚会用上】掌握了这些面试题,余生不在怕面试

    前言 上一篇文章总结了大厂经典面试系列之一:京东Java面试.接下来的文章我将陆续献上大厂的经典面试系列,所列的题目不代表所有,只是从面试者的口中总结的几次面试题,也是万千面试题的缩影,诣在帮助即将面 ...

  4. 2020年11个Redis系列高频面试题,哪些你还不会?

    前言 现在大家的工作生活基本已经是回归正轨了,最近也是迎来了跳槽面试季,有些人已经拿到了一两个offer了. 这段时间收集了阿里.腾讯.百度.京东.美团.字节跳动等公司的Java面试题,总结了Redi ...

  5. 李洪强iOS经典面试题36-简单介绍 ARC 以及 ARC 实现的原理

    李洪强iOS经典面试题36-简单介绍 ARC 以及 ARC 实现的原理 问题 简单介绍 ARC 以及 ARC 实现的原理. 考查点 ARC 是苹果在 WWDC 2011 提出来的技术,因此很多新入行的 ...

  6. 自然语言处理NLP星空智能对话机器人系列:第4、5、6、7次星空智能对话机器人Zoom线上演示安排

    自然语言处理NLP星空智能对话机器人系列:第4.5.6.7次星空智能对话机器人Zoom线上演示安排 月是故乡明.祝福大家和家人中秋节一切喜悦圆满 由于过节等因素,需要把9月19号的在第4次星空智能对话 ...

  7. VSLAM系列原创04讲 | 四叉树实现ORB特征点均匀化分布:原理+代码

    本文系ORB-SLAM2原理+代码实战系列原创文章,对应的视频课程见: 如何真正搞透视觉SLAM? 大家好,从今天开始我们陆续更新ORB-SLAM2/3系列的原创文章,以小白和师兄对话的形式阐述背景原 ...

  8. “约见”面试官系列之常见面试题第四十四篇之webpack打包原理解析?(建议收藏)

    webpack打包是如何运行的 也可以称为,webpack是如何实现模块化的 CommonJS是同步加载模块,一般用于node.因为node应用程序运行在服务器上,程序通过文件系统可以直接读取到各个模 ...

  9. ktor框架用到了netty吗_Netty系列相关面试题汇总

    Netty是一个高性能的框架,使用的地方非常多,面试题也经常提问.本套题来源比较多,最主要的来源是ThinkWon,地址是https://thinkwon.blog.csdn.net/article/ ...

最新文章

  1. C# .NET Web API 如何自訂 ModelBinder
  2. Python 小把戏之下载小说
  3. ubuntu14.04、CentOS安装oracle 11g数据库【转载】
  4. 移动应用用户使用成本控制管理
  5. 10个让人厌烦的编程语言
  6. springboot-文件上传xls及POI操作Excel
  7. cuda nsight 调试和性能分析
  8. python 中的if else 和in
  9. Oracle 20c 新特性:基础级内存数据库免费功能 In-Memory Base Level
  10. 自然语言处理包pytorch、torchvision、torchtext安装(亲测有效)
  11. 1.C#基础学习笔记3---C#字符串(转义符和内存存储无关)
  12. 学习Java,真的可以月薪过万嘛?真实个人经历告诉你,记录了平时学习的内容以及学习过程中最真实的感受(二)
  13. java注解拦截_轻松实现java拦截器+自定义注解
  14. 【IT基础】如何休息(每天都很累,但你真的会正确的休息方式么)
  15. GeoTrans2.4.1 用户手册 之 (六)笔记
  16. C/C++ 宏参数名前加#变为字符串
  17. Linux各运行级别含义,描述Linux运行级别0-6的各自含义
  18. DID会固定年份吗_双重差分方法(DID)解析、影响机制分析与三重差分方法(DDD)...
  19. C#|Winform编程之(列表视图控件)listView控件
  20. 如何为您的插件创建一个很棒的WordPress.org页面

热门文章

  1. php谷歌收录接口,php实现查询百度google收录情况(示例代码)
  2. java 生成xml乱码_jdom解决中文乱码问题 JAVA生成xml文件帮了我很大的忙
  3. python自动化框架pytest pdf_Python 自动化测试框架 unittest 和 pytest 对比
  4. vmware nat模式网络不通_【EVENG入门】 03EVENG网络运行环境(桥接模式、NAT模式、Cloud连接虚拟设备)...
  5. nextboolean()_Java Random nextBoolean()方法与示例
  6. java 方法 示例_Java语言环境getDisplayVariant()方法与示例
  7. 附录:更多字典操作命令
  8. 简易数字时钟软件详细制作过程
  9. rest风格的get加密字符串怎么接收_RESTful Api的设计与风格,你该学一下咯
  10. mfc 子窗体 按钮不触发_VBA与Excel入门——用户窗体1