Kafka 探险 - 架构简介

这个 Kafka 的专题,我会从系统整体架构,设计到代码落地。和大家一起杠源码,学技巧,涨知识。希望大家持续关注一起见证成长!

我相信:技术的道路,十年如一日!十年磨一剑!

简介

Kafka 是一种分布式的,基于发布 / 订阅的消息系统。最初被 LinkedIn 开发,并在 2011 年初开源,2012 年 10 月从 Apache 孵化器破壳而出,成为 Apache 的顶级项目。

Kafka 最初被设计的目的是 LinkedIn 流量和运维数据分析。流量数据包含 PV (Page View) , UV (Unique Visitor) ,搜索数据,详情页数据等。在高并发场景对于这些数据的统计并非实时的,不是简单的对于数据库的某个字段数据量 +1 这么简单,超大的流量洪峰下并不能因为统计数据将业务主流程阻塞。所以通常会将这些数据记录在文件或大数据存储引擎中,然后周期性的进行统计分析。

Kafka 被越来越多的公司青睐主要和他的特性优势有关:

  • 以 O(1) 时间复杂度消息持久化,对于 TB 级别的数据也能够保证 O(1) 的访问效率
  • 支持批量  和  数据,并且对于数据进行压缩保证高吞吐
  • 支持消息分区,分布式发送,分布式消费,便于水平扩展 (Scale out),具有很高的并发能力

应用场景

那为何需要使用消息队列,或者说在什么场景下 Kafka 更加合适

解耦

在大数据,高并发的场景下为了突破性能瓶颈会对系统进行水平扩展和垂直拆分,将一个复杂的系统拆分多个独立,纯净的子系统。数据在各个系统之间流转,但是如果某一个服务处理速度过慢,就会拖累整个链路的性能,形成瓶颈降低整个系统的性能,造成“旱的旱死涝的涝死”的局面。

举个简单例子:在淘宝下单时,交易系统完成扣款,后续会有很多动作:提醒卖家发货,生成卖家工作流,核销优惠券,增加购物积分等等,如果这一步全部写到交易系统的扣款代码之后,很有可能交易系统就会被拖死,下游任何一个环节失败也会导致扣款回滚,并且如果需要添加一个新的动作需要交易去做大量修改,设计肯定是不合理的。实际上交易系统在处理完扣款后会发送一个扣款完成消息,下游接这个消息即可,下游失败不会影响核心流程失败,并且各个系统的边界更加清楚,分层更更加合理。

数据持久化

如今的应用程序基本都会涉及到多个系统之间的对接,数据在系统之间通过 RPC 进行传递,处理数据的过程失败就会导致数据丢失,除非数据被持久化到磁盘上。而 Kafka 将所有需要流转的数据都 持久化到磁盘上 ,保证数据不会丢失。另外还有一个很重要的能力就是保留现场便于后续问题排查跟踪,经历过系统失败但是无法复现的人才会体会到的痛!

为了保证磁盘上的数据不会爆炸式疯涨,Kafka 提供了数据清理,数据压缩等功能,清除处理完成的历史数据。

扩展性

在应用的访问量剧增的情况下,代码优化往往没有直接进行水平扩展来的那么及时。诊断,分析,方案,优化,验证 一系列复杂流程让代码优化看起来只能是一个从长计议的方案。这时止血的方案只能是降级,限流,扩机器 三板斧。Kafka 的扩展性主要就体现在能热扩容,不需要修改参数,不需要修改代码,上机器 -> 注册服务 就完成了扩容。并非所有系统都具备这个像 调节音量旋钮一样简单的提高系统性能 的能力 ,这里会涉及到扩容之前的数据是否会有热点,新节点对集群的同步,流量重分配等等一系列复杂流程。

容灾

系统的部分组件失败不会影响这个系统的运行,消息队列降低了进程间的耦合度,上游或者下游服务挂掉后不会影响其他系统的运行,在服务重新在线后能够继续处理之前未处理的数据,只是会存在一定的延时但是能够保证 最终业务正确性 。

保序

强哥:你这瓜保熟吗?哦不,你这队列保序吗?

在大多数场景下,数据处理顺序是至关重要的,顺序错乱很可能导致数据结果错误。除非这个处理过程是无状态的,此时消息只是起到事件触发的作用,触发下游进行计算。Kafka 可以保证分区内部有序而不能保证全局有序。

核心概念

架构图

上图是一个典型的 Kafka 架构图,左边为消息生产者(Producer) ,发送消息到一个特定的主题(Topic),由于 Kafka 的分布式设计每个 Topic 被分成多个分区,因此发送到每个 Topic 的消息会被存储到对应的分区。另外如果 Topic 设置了副本,则每个分区都会有对应的副本。这些 Topic 被不同的消费者(Consumer)订阅,如果两个消费者在同一个消费者组,那么里面的消费者只能订阅一个固定的分区。

用上图的 Topic A 举例, Producer 1 发送消息到 Topic-A ,消息会在存放在 Broker-2 和 Broker-3 的两个分区上,并且由于 Topic-A 开启了分区备份,所以每个分区都会由另外一个节点 Topic-A' 备份分区数据 。发送到 Broker 的数据会被消费者订阅,由于 Consumer-1 和 Consumer-2 在同一个消费者组中,他们只能消费一个固定分区的消息, Consumer-1 只会接收到 Topic-A Partition-1 的消息,Consumer-2 只会接收到 Topic-A Partition-0 的消息。

Broker

在 Kafka 集群中的一个 Kafka Server 就是一个 Broker ,生产者将消息投递到 Broker ,Broker 保证消息的 持久化,容灾,准确性等。同时接受消费者的消息订阅,向消费者分发消息。一般来说在生产环境一台 Kafka 服务器就是一个 Broker。

Topic & Partition & Log

Topic 可以认为是用来存储消息的逻辑概念,可简单认为他是一个 信箱 。每条消息发送的时候都需要指定需要发送到哪个 Topic ,消息被消费的时候也需要指定消费哪个 Topic 中的消息。

Kafka 为了提高可扩展性以及吞吐量,Topic 被分成多个分区 (Partition) ,每个 Partition 对应一个 Log,Log 是一个逻辑概念, 它会对应服务器上一个文件夹,这个文件夹下存放的是这个 Partition 下所有的消息数据和消息索引 。在面对海量数据的时候,为了避免出现巨大文件出现 I/O 瓶颈,Kafka 又将 Log 分为多个 Segment 。每个 Segment 包含 log 文件  和 index 文件 文件命名是以该 Segment 第一条消息的 offset 命名。这样说下来其实还是很绕的直接看下面的架构图,可以仔细留意一下各个部分的标识和数字再结合这段文字,理解起来应该就很轻松了。

另外因为 Kafka 采用顺序 I/O,顺序 I/O 效率非常高,甚至比随机写内存效率更高,这也是 Kafka 高性能的原因之一。

Replication

在生产环境中,我们一般会开启 Kafka 消息冗余特性,每个 Partition 都有 1 个或多个副本,我们称之为 Replication。当分区只有一个副本的时候,该分区数据只保留了一份。每个分区副本都会选出一个 Leader , Leader 是所有读写请求的 “接口人”  ,其余副本均为 Follower 。Follower 作用有两个:拉取 Leader 的 Log 数据做 备份 ,在 Leader 失败后作为候选人 参与 Leader 选举 。

Producer

消息产出的源头,通过一定的策略推送到 Topic 的各个分区 。这里所说的推送策略就是消息路由机制,Kafka 内置多种策略可选例如:按照消息 Key ,轮训等等,甚至用户可以写扩展代码来自定义路由策略。

Consumer & Consumer Group

消费者(Consumer) 主要工作是从 Broker 拉取消息,进行消费处理。每个消费者维护自己的消费进度,这样的设计有诸多好处,比如:每个消费者进度能够轻松的进行区分,并且可以修改单个消费者的消费位点跳过或者重新消费某些消息,避免了位点信息的集中化管理的单点故障问题。

现在的应用程序大部分为分布式的系统,一个应用有几十台上百台服务器,这些服务器上运行着相同的代码,那么一个消息过来,每台服务器都执行一次消费逻辑,岂不是会造成巨大的问题。

所以 Kafka 引入了一个新的概念: 消费者组(Consumer Group) 。我们可以将这些应用的服务器都放到同一个消费者组中,而 Kafka 规定一条消息只能被同一个消费者组中的一个消费者消费,这样就能完美避免分布式情况下的重复消费问题了。上面所说的情况简单来说是希望实现消息被某台服务器独占,也就是 单播 问题。假如我们希望这条消息被广播出去,每台收到这个消息的服务器都做处理,例如发消息做日志清理,这种情况称为 广播 , 那我们只需要将每个消费者放到不同的消费者组即可。

Kafka 引入消费者组的概念巧妙解决了单播和广播问题,而没有区分订阅类型,通过一种逻辑概念来屏蔽掉多种订阅实现。

另外在同一个消费者组中的消费者订阅的分区是确定的,只有在消费者组中的消费者有变化的时候才会进行重分配。例如我们有四个分区,三个消费者,就会出现一个消费者订阅两个分区的情况。而三个分区四个消费者就会出现有消费者处于空闲状态,造成浪费,所以一般消费者的数量尽量不要大于 Topic 的分区数。

尾声(唠叨)

这是我 2021 年的第一篇博客,年底做回顾的时候才知道去年我过的究竟有多么糟糕。既没有输入也没有输出,虽然工作进入一个新的阶段,会越来越忙,但忙不是拒绝成长的借口,必须保证每月一到两本书的输入,一到两周输出一篇优质文章。 最长的路属于一颗孤独的心,与君共勉

下期我会从整体梳理 Kafka 生产者,包括消息发送客户端,发送端数据缓存从源码角度看看其中的设计模式,代码组织技巧。

Kafka 探险 - 架构简介的更多相关文章

  1. Kafka:架构简介【转】

    转:http://www.cnblogs.com/f1194361820/p/6026313.html Kafka 架构简介 Kafka是一个开源的.分布式的.可分区的.可复制的基于日志提交的发布订阅 ...

  2. Kafka 探险 - 生产者源码分析: 核心组件

    这个 Kafka 的专题,我会从系统整体架构,设计到代码落地.和大家一起杠源码,学技巧,涨知识.希望大家持续关注一起见证成长! 我相信:技术的道路,十年如一日!十年磨一剑! 往期文章 Kafka 探险 ...

  3. Kafka架构简介

    一.kafka的架构 1.Broker kafka集群包含一个或者多个服务器,这种服务器就叫做Broker 2.Topic 每条发布到kafka集群的消息都有一个类别,这个类别就叫做Topic(逻辑上 ...

  4. Zookeeper、Kafka集群与Filebeat+Kafka+ELK架构

    Zookeeper.Kafka集群与Filebeat+Kafka+ELK架构 目录 Zookeeper.Kafka集群与Filebeat+Kafka+ELK架构 一.Zookeeper 1. Zook ...

  5. LoadRunner系统架构简介

    1.LoadRunner系统架构简介 LoadRunner是通过创建虚拟用户来代替真实实际用户来操作客户端软件比如Internet Explorer,来向IIS.Apache等Web服务器发送HTTP ...

  6. crtmpserver的架构简介

    crtmpserver的架构简介 一.层 Layers . 机器层 Machine layer . 操作系统层 Operating System Layer   This layer is compo ...

  7. Extjs6官方文档译文——应用架构简介(MVC,MVVM)

    应用架构简介 Extjs 同时提供对于MVC和MVVM应用架构的支持.这两个架构方式共享某些概念,而且都旨在沿着逻辑层面划分应用程序代码.每种方法在选择如何划分应用组件上都有其各自的优势. 本指南的目 ...

  8. 揭秘Kafka高性能架构之道 - Kafka设计解析(六)

    原创文章,同步首发自作者个人博客.转载请务必在文章开头处以超链接形式注明出处http://www.jasongj.com/kafka/high_throughput/ 摘要 上一篇文章<Kafk ...

  9. Kafka学习之路 (二)Kafka的架构

    一.Kafka的架构 如上图所示,一个典型的Kafka集群中包含若干Producer(可以是web前端产生的Page View,或者是服务器日志,系统CPU.Memory等),若干broker(Kaf ...

随机推荐

  1. Day6 Scrum 冲刺博客

    一.站立式会议# 1. 会议照片 2. 工作进度+燃尽图  团队成员 昨日完成工作  今日工作计划 遇到的困难  周梓波  将方块旋转变形  添加键盘监听事件  不熟悉监听事件的操作  纪昂学  左右 ...

  2. 【杂记】CSP-S 2020 游记 &反思

    考场经历 吐槽:为什么这个 Enter 的位置怎么诡异啊老是打错.要是考挂了就怪你 开场当然先看了 T1,发现是个日期转换,果然是个百出不厌的模拟题类型,估价细节多到爆炸.看了几分钟题目,对这些规则云 ...

  3. js-enter提交表单导致页面刷新问题

    问题:当页面只有一个文本框时,使用键盘enter操作执行提交表单的时候,会导致页面进行刷新,并且参数也会自动添加到url中. 解决办法: 1.给form添加onsubmit=return false; ...

  4. STL——容器(Set & multiset) insert 的返回值 和 pair 的用法

    1. 使用 insert 插入时的返回值: 将一个元素插入 (insert) 到 set 或 multiset 中时,如果插入失败返回的类型是一个 pair 的自定类型,insert 源码如下: in ...

  5. sql 语句使用和转换json数据

    1 连接mysql import pymysql import concurrent coon=pymysql.connect(host='localhost',user='root',passwor ...

  6. 简易CLI

    使用C语言实现一个简易的CLI,命令通过模式进行划分,实现效果如下: 代码较为简单,主要是为了方便进行移植,这里就不进行详细的说明了. 代码路径:https://github.com/zhengcix ...

  7. ECharts的下载和安装(图文详解)

    首先搜索找到ECharts官网,点击进入. 找到下载 进入就看到第三步,就点击在线制作 点击进入之后就自己可以选择里面的形状图,就在线制作.最后生成echarts.min.js 点击下载后就会生成js ...

  8. ActiveMq反序列化漏洞(CVE-2015-5254)漏洞复现

    漏洞原理 Apache ActiveMQ 5.13.0之前5.x版本中存在安全漏洞,该漏洞源于程序没有限制可在代理中序列化的类.远程攻击者可借助特制的序列化的Java Message Service( ...

  9. XCTF EasyHook

    无壳,使用IDA直接分析主函数 逻辑很简单,问题的关键是Hook,题目也是EasyHook, 会发现在生成文件后,文件内容是被加密后的,那就怀疑加密函数参与Hook 动态调试一步步来看,先进入4012 ...

  10. [UWP] - Adaptive Trigger Featurede的使用方法及效果

    XAML代码: <Page.Resources> <!-- DataTemplate to use in the portrait layout. --> <DataTe ...