关于kafka:对于Kafka的基本认识

5次阅读

共计 9807 个字符,预计需要花费 25 分钟才能阅读完成。

对于 Kafka 的根本意识

  • 在我的项目中应用到了 Kafka 作为音讯队列中间件以同步容器状态,然而对于为什么应用 Kafka,以及与其余的音讯队列中间件有什么区别不甚了解,因而撰写此文,作为日后学习 Kafka 的入门文章

音讯队列的简介

音讯队列的基本功能

  • 解耦

    • 各个服务之间不是间接的调用关系,而是应用音讯队列进行解耦,音讯的生产者不必关系音讯如何被生产,消费者也不必关怀音讯如何被生产

      • 能够联想下线程池中的阻塞工作队列
  • 异步

    • 对于一些同步操作,比拟消耗工夫,导致响应会比较慢,如果不要求强实时性,就能够应用音讯队列将其转为异步执行的工作

      • 比方短信服务、邮件服务等等
    • 除了思考到同步操作耗时之外,还有一些人造的异步动作,比方我的项目中的容器状态同步,须要应用到音讯队列来维持
  • 削峰

    • 相当于做了一个蓄水池,申请比拟少时安然无恙,申请激增时应用音讯队列缓存申请(申请能够疾速的返回),生产零碎再去拉取音讯进行解决

      • 和限流算法中的令牌桶算法比拟相似

音讯队列的毛病

  • 升高零碎的可用性:零碎引入的内部依赖越多,越容易挂掉
  • 零碎复杂度进步 应用 MQ 后可能须要解决音讯没有被反复生产(音讯队列的幂等性问题)、音讯失落的状况,保障消息传递的程序性等等问题

    • 音讯有序性
    • 音讯失落
    • 音讯反复生产

音讯队列的两个实现标准

JMS
  • JMS(Java Message Service)是 Java 的音讯服务,能够视作一套 API 规范
  • 反对队列模型与公布订阅模型
  • ActiveMQ 就是基于 JMS 标准实现的
AMQP
  • AMQP,即 Advanced Message Queuing Protocol,一个提供对立音讯服务的应用层规范 高级音讯队列协定 (二进制应用层协定),是应用层协定的一个凋谢规范,为面向音讯的中间件设计, 兼容 JMS基于此协定的客户端与消息中间件可传递音讯,并不受客户端 / 中间件产品类型,开发语言等条件的限度

    • 一套应用层协定而非 API
    • 跨语言与平台
    • 仅反对二进制数据

音讯队列零碎的几个要害的问题

音讯队列中的音讯大量积压
  • 可能的起因就是 生产端挂掉了,导致大量数据存储在音讯队列不能被生产

    • 首先复原 consumer 的问题,保障其可用
    • 新建一个 topic Partition 设置为失常的十倍(视状况而定)

      • 从新投递并生产是必要的,然而数据量比拟大,所以须要设置一个 Partition 扩充的 topic
    • 长期写一个 consumer,生产积压的数据,而后从新投递到新的 topic 中,次要的就是保障 consumer 疾速生产,而不像一般的 consumer 可能做一些比拟耗时的操作
    • 长期加服务器扩容 consumer(也为之前的十倍,视状况而定)生产对应的 topic 中的数据
    • 生产结束后,进行可能的架构降级以保障后续不再产生生产端挂掉的状况
音讯失落
  • 这里指的是因为音讯积压带来的音讯失落,手动写长期的程序,查出失落的程序,再将其投喂到音讯零碎中

    • 前面有防止音讯失落的三个维度的计划

Kafka 简介

  • Kafka 是由 LinkedIn 开发的一个 分布式 的基于 公布 / 订阅模型 的音讯零碎,应用 Scala 编写,它以 可程度扩大 高吞吐率(高性能)而被宽泛应用,同时反对 音讯长久化。Kafka 并不是 JMS 或 AMQP 任一规范的实现,Kafka 自成规范

    • 程度扩大:反对 broker 的增加与 topic 的 Partition 的扩大
    • 高吞吐率,生产者将音讯 push 到 Partition 的形式是追加的形式,是磁盘的程序 IO,性能比拟高,并且因为同一主题能够有多个 Partition,因而吞吐率高
  • Kafka 对音讯保留时依据 Topic 进行归类,发送音讯者称为 Producer,音讯接受者称为 Consumer,此外 Kafka 集群有多个 Kafka 实例组成,每个实例 (server) 称为 broker

常见的应用场景

音讯零碎

  • Kafka 与传统的消息中间件都具备 零碎解耦 冗余存储 流量削峰 缓冲 异步通信 扩展性 可恢复性 等性能。与此同时,Kafka 还提供了大多数音讯零碎难以实现的 音讯程序性保障及回溯性生产 的性能
  • 晚期的时候 Kafka 并不是一个合格的音讯队列,这也和 LinkedIn 最早开发 Kafka 用于解决海量的日志有很大关系,并不是作为音讯队列应用的,随着后续的倒退,这些短板都被 Kafka 逐渐修复欠缺

存储系统

  • Kafka 把音讯长久化到磁盘,相比于其余基于内存存储的零碎而言,无效的升高了音讯失落的危险。这得益于其 音讯长久化 多正本机制 。也 能够将 Kafka 作为长期的存储系统来应用,只须要把对应的数据保留策略设置为“永恒”或启用主题日志压缩性能

流式解决平台

  • Kafka 为风行的流式解决框架提供了牢靠的数据起源,还提供了一个残缺的流式解决框架,比方窗口、连贯、变换和聚合等各类操作

Website activity tracking

Kafka 能够作为 网站活性跟踪 的最佳工具;能够将网页 / 用户操作等信息发送到 Kafka 中,并实时监控,或者离线统计分析等

Metrics

Kafka 通常被用于可操作的监控数据。这包含从分布式应用程序来的聚合统计用来生产集中的经营数据提要

Log Aggregation

Kafka 的个性决定它非常适合作为 日志收集核心 ;application 能够将操作日志 批量异步 的发送到 Kafka 集群中,而不是保留在本地或者 DB 中;Kafka 能够批量提交音讯 / 压缩音讯等,这对 producer 端而言,简直感觉不到性能的开销,此时 consumer 端能够是 hadoop 等其余系统化的存储和剖析零碎

Kafka 的装置与应用办法

  • 举荐看另一篇文章,应用 docker-compose 部署 Kafka

Kafka 根底

队列模型与公布订阅模型

队列模型(一对一)
  • 应用队列保护音讯,只能保障一个音讯被一个消费者生产,当须要将特定的音讯分发给多个消费者时,则不适合了,能够应用线程池中的 BlockingQueue 来了解队列模型

    • 比方有多个消费者连贯了同一个音讯队列,当生产者发送多条音讯 A B C D 后,多个 Consumer 可能别离只承受到其中一个音讯,这个过程是不受控的,因而队列模型更实用于一对一的音讯公布
公布订阅模型
  • 通过订阅主题的形式实现音讯向多个消费者的散发
  • 在公布 – 订阅模型中,如果只有一个订阅者,那它和队列模型就根本是一样的了。所以说,公布 – 订阅模型在性能层面上是能够兼容队列模型的
  • 要留神的是 Kafka 的公布订阅模型中没有队列这个概念(即消息传递通道的角色),只有 Partition 的概念(实际上 Partition 用来反对某主题对应的音讯通道的程度扩大)

Kafka 应用的公布订阅模型

  • 常见的架构图

    <img src=”https://images.demoli.xyz/image-20210803211115318.png” alt=”image-20210803211115318″ style=”zoom:67%;” />

    • 无论是 Kafka 集群,还是 consumer 都依赖于 Zookeeper 集群保留一些 meta 信息,来保证系统可用性,不过在 Kafka 的 2.8 版本就曾经开始尝试摈弃 Zookeeper 了

      • Zookeeper 是 Kafka 用来负责集群元数据管理、控制器选举等操作的
      • 对于 Kafka2.8 版本摈弃 Zookeeper 的状况,可参考这篇文章

根底概念

Broker
  • Kafka 集群蕴含一个或多个服务器,这种服务器被称为 broker。broker 不保护数据的生产状态,间接应用磁盘进行音讯存储,线性读写,速度快:防止了数据在 JVM 内存和零碎内存之间的复制,缩小耗性能的创建对象和垃圾回收
Cluster Controller
  • 若干个 Broker 组成一个 集群 其中集群内某个 Broker 会成为 集群控制器,它负责管理集群,包含调配 Partition 到 Broker、监控 Broker 故障等
Producer
  • 负责公布音讯到 Kafka broker
  • producer 采纳 推(push)模式 将音讯公布到 broker,每条音讯都被追加(append)到 Partition(patition)中,属于程序写磁盘(程序写磁盘效率比随机写内存要高,保障 Kafka 吞吐率)

  • 每个 Partition 中的音讯都是 有序 的,生产的音讯被一直追加到 Partition log 上,其中的每一个音讯都被赋予了一个惟一的 offset

    • 留神是同一个 Partition 内的音讯是有序的,同一个主题的多个 Partition 之间不是有序的
    • 消费者生产的地位由 offset 指定,offset 自身由消费者维持,broker 不保护此值(保障性能)

      • 能够应用 zookeeper 来保护生产状态
  • push 音讯时指定 key 和 Partition,同一个 key 的音讯,应用同一个 Partition,保障音讯有序,这里的 key 实际上指代的是某业务,某对象的 id
Consumer
  • 音讯消费者,向 Kafka broker 读取音讯的客户端,consumer 从 broker拉取 (pull) 数据并进行解决
Topic
  • Producer 将音讯发送到特定的主题,Consumer 通过订阅特定的 Topic(主题) 来生产音讯

    • 同一个主题的音讯可能存储在不同的节点(实际上是其对应的传输通道 –Partition 能够散布在不同的节点上),然而消费者不必关怀具体的存储地位
  • 一个主题的音讯能够对应多个 Partition,即应用多个 Partition 传输该主题的音讯
Partition
  • 在集群内,一个 Partition 由一个 Broker 负责,这个 Broker 也称为这个 Partition 的 Leader;当然一个 Partition 能够被复制到多个 Broker 上来实现冗余,这样当存在 Broker 故障时能够将其 Partition 重新分配到其余 Broker 来负责
  • 设计 Partition 的起因

    • 不便在集群中扩大,每个 Partition 能够通过调整以适应它所在的机器,而一个 topic 又能够有多个 Partition 组成,因而整个集群就能够适应任意大小的数据了
    • Kafka 通过给特定 Topic 指定多个 Partition, 而各个 Partition 能够散布在不同的 Broker 上, 这样便能提供比拟好的并发能力(负载平衡)
  • Partition 的多正本机制

    • Partition 中的多个正本之间会有一个叫做 leader 的家伙,其余正本称为 follower。咱们发送的音讯会被发送到 leader 正本,而后 follower 正本(做冷备)能力从 leader 正本中拉取音讯进行同步
    • Kafka 会平均的将一个 partition 的所有 replica 散布在不同的机器上,这样才能够进步容错性

      • <span style=’color:blue;background: 背景色彩;font-size: 文字大小;’>晋升了信息的安全性,避免音讯失落,进步了容灾能力,然而同时也减少了占用的空间</span>

      生产者和消费者只与 leader 正本交互。能够了解为其余正本只是 leader 正本的拷贝,它们的存在只是为了保障音讯存储的安全性。当 leader 正本产生故障时会从 follower 中选举出一个 leader, 然而 follower 中如果有和 leader 同步水平达不到要求的加入不了 leader 的竞选。

Zookeeper 在 Kafka 中起到的作用

  • 次要就是服务发现与元数据的存储,与每一个分布式系统中的元数据存储一样(比方 Spring loud 中的 eureka),就是一个加了事件告诉机制的分布式数据库,次要用来做服务发现与服务治理
  • Broker 注册 :在 Zookeeper 上会有一个专门 用来进行 Broker 服务器列表记录 的节点。每个 Broker 在启动时,都会到 Zookeeper 上进行注册,即到 /brokers/ids 下创立属于本人的节点。每个 Broker 就会将本人的 IP 地址和端口等信息记录到该节点中去
  • Topic 注册 :在 Kafka 中,同一个Topic 的音讯会被分成多个 Partition 并将其散布在多个 Broker 上,这些 Partition 信息及与 Broker 的对应关系 也都是由 Zookeeper 在保护。比方创立了一个名字为 my-topic 的主题并且它有两个 Partition,对应到 zookeeper 中会创立这些文件夹:/brokers/topics/my-topic/Partitions/0/brokers/topics/my-topic/Partitions/1
  • 负载平衡:下面也说过了 Kafka 通过给特定 Topic 指定多个 Partition, 而各个 Partition 能够散布在不同的 Broker 上, 这样便能提供比拟好的并发能力。对于同一个 Topic 的不同 Partition,Kafka 会尽力将这些 Partition 散布到不同的 Broker 服务器上。当生产者产生音讯后也会尽量投递到不同 Broker 的 Partition 外面。当 Consumer 生产的时候,Zookeeper 能够依据以后的 Partition 数量以及 Consumer 数量来实现动静负载平衡。
  • ……

Kafka 如何保障音讯不失落

生产者的音讯失落
  • 生产者的音讯发送是异步的,应该增加回调,再发送失败后,执行重发
  • 设置生产者的主动重试次数,当网络呈现问题时会主动重发,个别是 3,然而为了保障音讯不失落的话个别会设置比拟大一点。设置实现之后,当呈现网络问题之后可能主动重试音讯发送,防止音讯失落。另外,倡议还要设置重试距离,因为距离太小的话重试的成果就不显著了

    • 可能导致音讯的反复发送
消费者的音讯失落
  • 当消费者拉取到了 Partition 的某个音讯之后,消费者会主动提交了 offset。主动提交的话会有一个问题,试想一下,当消费者刚拿到这个音讯筹备进行真正生产的时候,忽然挂掉了,音讯实际上并没有被生产,然而 offset 却被主动提交了。

    • 解决办法也比拟粗犷,手动敞开主动提交 offset,每次在真正生产完音讯之后之后再本人手动提交 offset。然而会带来音讯被从新生产的问题。比方刚刚生产完音讯之后,还没提交 offset,后果挂掉了,那么这个音讯实践上就会被生产两次
Kafka 本身丢了音讯
  • 从 Partition 的多正本机制中 follower 没有实现对于 leader 的同步,然而 leader 所在的 broker 挂掉的状况开始谈起

    • Kafka 为 Partition 引入了多正本(Replica)机制。Partition 中的多个正本之间会有一个叫做 leader 的家伙,其余正本称为 follower。咱们发送的音讯会被发送到 leader 正本,而后 follower 正本能力从 leader 正本中拉取音讯进行同步。生产者和消费者只与 leader 正本交互。能够了解为其余正本只是 leader 正本的拷贝,它们的存在只是为了保障音讯存储的安全性。
    • 试想一种状况:如果 leader 正本所在的 broker 忽然挂掉,那么就要从 follower 正本从新选出一个 leader,然而 leader 的数据还有一些没有被 follower 正本的同步的话,就会造成音讯失落。解决办法如下所示:

      • 设置 acks = all,acks 是 Kafka Producer 很重要的一个参数。acks 的默认值即为 1,代表咱们的音讯被 leader 正本接管之后就算被胜利发送。当咱们配置 acks = all 代表则所有正本都要接管到该音讯之后该音讯才算真正胜利被发送
      • 设置 replication.factor >= 3,为了保障 leader 副本能有 follower 副本能同步音讯,咱们个别会为 topic 设置 replication.factor >= 3。这样就能够保障每个 Partition(partition) 至多有 3 个正本。尽管造成了数据冗余,然而带来了数据的安全性
      • 设置 min.insync.replicas > 1,个别状况下咱们还须要设置 min.insync.replicas> 1,这样配置代表音讯至多要被写入到 2 个正本才算是被胜利发送。min.insync.replicas 的默认值为 1,在理论生产中应尽量避免默认值 1。
      • 为了保障整个 Kafka 服务的高可用性,还须要确保 replication.factor > min.insync.replicas。为什么呢?构想一下如果两者相等的话,只有是有一个正本挂掉,整个 Partition 就无奈失常工作了。这显著违反高可用性!个别举荐设置成 replication.factor = min.insync.replicas + 1
      • 设置 unclean.leader.election.enable = false,咱们发送的音讯会被发送到 leader 正本,而后 follower 正本能力从 leader 正本中拉取音讯进行同步。多个 follower 正本之间的音讯同步状况不一样,当咱们配置了 unclean.leader.election.enable = false,当 leader 正本产生故障时就不会从 follower 正本中和 leader 同步水平达不到要求的正本中抉择出 leader,这样升高了音讯失落的可能性。

        Kafka 0.11.0.0 版本开始 unclean.leader.election.enable 参数的默认值由原来的 true 改为 false

Kafka 如何保障音讯不反复(幂等问题)

  • 有一个观点要了解,即分布式的环境下,不失落音讯与不反复是矛盾的,然而相对来说反复生产是能够在生产端设计的,然而音讯失落就比拟麻烦了
呈现音讯反复的三种场景
  • 发送音讯时呈现反复

    • 音讯曾经被 push 到 broker,在 broker 响应之前,网络故障,生产者没有收到回应,认为没有胜利收回,于是反复发送
    • 其实就是前边说的为了保障生产者局部音讯不失落导致的
  • 生产音讯时呈现反复

    • 前文中生产端防止音讯失落的局部曾经阐明了
    • 所谓防止 Kafka 呈现音讯反复实质上指的是防止音讯被反复生产
  • broker 重启或者扩容缩容时呈现音讯的反复
解决方案
计划 1
  • 从关系型数据库的幂等性上思考(依赖于事务的音讯幂等计划)

    • 如果是插入数据的话,在插入前首先检查数据是否曾经存储了(曾经被生产了),如果没有再进行生产(数据的插入)
    • 然而如果是并发的反复音讯的话,这么查看也没有用 ,因而能够应用加共享锁的读select for update 然而又会导致并发度降落,于是又能够应用乐观锁等等,波及的业务表的波及就比较复杂了
    • 更正当的一个形式是在生产端的数据库中保护一个音讯生产的记录表,进行音讯生产时,把生产记录插入记录表与业务表的数据更新做到一个事务中去执行,就能够保障不会反复生产数据了(如果有反复音讯的话,会导致插入音讯表时呈现主键抵触),局限性在于事务带来的性能的耗费以及生产端的业务生产必须仅仅蕴含 MySQL 这样的关系型数据库,如果还波及到 Redis 等 nosql 的数据库,则有效了

      • 留神音讯生产记录表的记录 ID 应该是业务相干的 ID,而不是音讯 ID,因为如果生产者反复发送音讯的话,音讯 ID 也是不同的,可能导致音讯被重复记录,从而导致反复生产
计划 2
  • 不依赖于事务的音讯幂等计划,外围在于去重表(对于生产状态的保护)

<img src=”https://images.demoli.xyz/image-20210816184127192.png” alt=”image-20210816184127192″ style=”zoom:67%;” />

  • 所谓的去重表就是依赖事务的案例中的那个音讯生产记录表的一个新版本
  • 为什么要提早生产,提早生产阐明反复的音讯遇到了本音讯正在解决的场景,为了防止正在解决的失败,因而不是间接抛弃而是提早再生产,以保障音讯不会失落

    • <span style=’color:;background: 背景色彩;font-size: 文字大小;’>至于提早生产的形式能够是将音讯投到一个特定的 topic 中(或者是原 topic),而后有特定的生产端从新生产</span>
  • 为什么音讯生产记录表中的音讯记录要保护一个生产的工夫呢?还是上边的场景,如果第一个音讯没能胜利解决,而第二个音讯提早生产后,每次都是看到正在生产中,会导致音讯解决的失败,也就意味着音讯的失落,因而正在解决中的音讯有工夫阈值,规定工夫内没有生产实现的须要从表中删除,示意生产失败

    • 删除后,会始终进行重试提早生产
  • 去重表个别应用 Redis 保护,性能好,过期工夫还能够应用 Redis 的 ttl 实现

Kafka 性能原理

  • 程序读写

    • producer 采纳 推(push)模式 将音讯公布到 broker,每条音讯都被追加(append)到 Partition 中,属于程序写磁盘(程序写磁盘效率比随机写内存要高,保障 Kafka 吞吐率)
    • Kafka 默认不会删除长久化的数据,Kakfa 提供了两种策略来删除数据。一是基于工夫,二是基于 partition 文件大小。具体配置能够参看它的配置文档
  • 应用了操作系统的 Page Cache
  • 批量读写

    • 异步的思维,批量读写在 MySQL 中也有用到比方 redolog 的 wal 技术
  • Partition+ 分段 + 索引,进步数据读写效率,并发读写
  • 反对数据的批量压缩,以升高网络 IO 的工夫
  • 零拷贝

    • 零拷贝并非指一次拷贝都没有,而是防止了在内核空间和用户空间之间的拷贝
    • 生产过程中应用到了零拷贝
    • 防止了数据在 JVM 内存和零碎内存之间的复制,缩小耗性能的创建对象和垃圾回收

<img src=”https://images.demoli.xyz/image-20210815185423195.png” alt=”image-20210815185423195″ style=”zoom:67%;” />

其余音讯队列中间件

ActiveMQ

  • 长处

    • 单机吞吐量:万级
    • topic 数量都吞吐量的影响:
    • 时效性:ms 级
    • 可用性:高,基于 主从架构 实现高可用性
    • 音讯可靠性:有较低的概率失落数据
    • 性能反对:MQ 畛域的性能极其齐备
  • 毛病:

    • 官网社区当初对 ActiveMQ 5.x 保护越来越少,较少在大规模吞吐的场景中应用,然而 ActiveMQ Artemis 版本性能有了很大的晋升

Kafka

  • 长处

    • 性能卓越,单机写入 TPS 约在百万条 / 秒,最大的长处,就是吞吐量高
    • 时效性:ms 级
    • 可用性:十分高,Kafka 是分布式的,一个数据多个正本,多数机器宕机,不会失落数据,不会导致不可用
    • 消费者采纳 Pull 形式获取音讯, 音讯有序, 通过管制可能保障所有音讯被生产且仅被生产一次
    • 有优良的第三方 Kafka Web 治理界面 Kafka-Manager
    • 在日志畛域比拟成熟,被多家公司和多个开源我的项目应用
    • 性能反对:性能较为简单,次要反对简略的 MQ 性能,在大数据畛域的实时计算以及日志采集被大规模应用
  • 毛病

    • Kafka 单机超过 64 个队列 /Partition,Load 会产生显著的飙高景象,队列越多,load 越高,发送音讯响应工夫变长
    • 应用短轮询形式,实时性取决于轮询间隔时间
    • 生产失败不反对重试
    • 反对音讯程序,然而一台代理宕机后,就会产生音讯乱序
    • 社区更新较慢

RabbitMQ

  • 长处

    • 因为 erlang 语言的个性,mq 性能较好,高并发
    • 吞吐量到万级,MQ 性能比拟齐备
    • 强壮、稳固、易用、跨平台、反对多种语言、文档齐全
    • 开源提供的治理界面十分棒,用起来很好用
    • 社区活跃度高
  • 毛病

    • erlang 开发,很难去看懂源码,根本职能依赖于开源社区的疾速保护和修复 bug,不利于做二次开发和保护
    • RabbitMQ 的确吞吐量会低一些,这是因为他做的实现机制比拟重。
    • 须要学习比较复杂的接口和协定,学习和保护老本较高

RocketMQ

  • 长处

    • 单机吞吐量:十万级
    • 可用性:十分高,分布式架构
    • 音讯可靠性:通过参数优化配置,音讯能够做到 0 失落
    • 性能反对:MQ 性能较为欠缺,还是分布式的,扩展性好
    • 反对 10 亿级别的音讯沉积,不会因为沉积导致性能降落
    • 源码是 Kafka,咱们能够本人浏览源码,定制本人公司的 MQ,能够掌控
  • 毛病

    • 反对的客户端语言不多,目前是 Kafka 及 c ++,其中 c ++ 不成熟;
    • 社区活跃度个别
    • 没有在 mq 外围中去实现 JMS 等接口,有些零碎要迁徙须要批改大量代码

区别

  • Kafka 反对实时的流式解决
  • 极致的性能:基于 Scala 和 Kafka 语言开发,设计中大量应用了批量解决和异步的思维,最高能够每秒解决千万级别的音讯
  • 生态系统兼容性无可匹敌:Kafka 与周边生态系统的兼容性是最好的没有之一,尤其在大数据和流计算畛域(也能够形容为比拟好找材料)

参考

  • Kafka 常见面试题
  • 音讯队列的了解
  • 为什么 Kafka 性能这么好
  • 防止音讯反复生产的解决方案
  • Kafka 摈弃 Zookeeper
正文完
 0