Kafka简介
Kafka是什么
Kafka是一种高吞吐量的分布式发布订阅消息系统(消息引擎系统),它可以处理消费者在网站中的所有动作流数据。 这种动作(网页浏览,搜索和其他用户的行动)是在现代网络上的许多社会功能的一个关键因素。 这些数据通常是由于吞吐量的要求而通过处理日志和日志聚合来解决。 对于像Hadoop一样的日志数据和离线分析系统,但又要求实时处理的限制,这是一个可行的解决方案。Kafka的目的是通过Hadoop的并行加载机制来统一线上和离线的消息处理,也是为了通过集群来提供实时的消息。
简单来说就是一个生产者将数据发送给kafka,系统B从kafka中进行拉取自己所需要的东西
异步通信原理
观察者模式
生产者消费者模式
传统模式
- 生产者直接将消息传递给消费者
- 耦合性非常高,当生产者或消费者发生改变,都需要重写业务逻辑
生产者消费者模式
- 通过一个容器解决生产者和消费者的强耦合关系,生产者和消费者彼此之间不直接进行联系,而是通过阻塞队列来进行通讯
数据传递流程
- 生产者消费者模式:有N个线程进行生产,同时N个线程进行消费,两种角色通过内存缓冲区进行通信
- 生产者负责向缓冲区中添加数据单元
- 消费者负责从缓冲区中拉取自己所需数据单元
-
一般情况下都是遵循先进先出原则
-
消息队列
目前企业中常见的消息队列产品主要有:Kafka,ActiveMQ,Rabbit,RocketMQ,在大数据中主要采用Kafka作为消息队列
传统消息队列应用场景
- 缓存/削峰:有助于控制和优化数据流经过系统的速度,解决生产消息和消费消息的处理不一致情况
-
- 解耦:允许独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束
- 异步通信:允许用户将一个消息放入队列,但并不立即处理,当需要的时候在处理这个消息
消息队列的两种模式
- 点对点模式
- 消费者主动拉取数据,消息拉取完成后清除消息
- 发布/订阅模式
- 可以有多个topic主题(浏览,点赞,收藏。。。)
- 消费者消费数据之后不删除数据
- 每个消费者之间相互独立,都可以消费数据
使用消息队列的好处
-
解耦:允许我们独立的扩展或修改队列两边的处理过程。
-
异步通信:消息队列允许用户把消息放入队列但不立即处理它。
-
灵活性 & 峰值处理能力:不会因为突发的超负荷的请求而完全崩溃,消息队列能够使关键组件顶住突发的访问压力。
-
缓冲:有助于解决生产消息和消费消息的处理速度不一致的情况。
-
可恢复性:即使一个处理消息的进程挂掉,加入队列中的消息仍然可以在系统恢复后被处理
kafka的优点
解耦
在项目启动之初来预测将来项目会碰到什么需求,是极其困难的。消息系统在处理过程中间插入了一个隐含的、基于数据的接口层,两边的处理过程都要实现这一接口。这允许你独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束
扩展性
因为消息队列解耦了你的处理过程,所以增大消息入队和处理的频率是很容易的,只要另外增加处理过程即可。不需要改变代码、不需要调节参数。
灵活性&峰值处理
在访问量剧增的情况下,应用仍然需要继续发挥作用,但是这样的突发流量并不常见;如果为以能处理这类峰值访问为标准来投入资源随时待命无疑是巨大的浪费。使用消息队列能够使关键组件顶住突发的访问压力,而不会因为突发的超负荷的请求而完全崩溃
可恢复性
系统的一部分组件失效时,不会影响到整个系统。消息队列降低了进程间的耦合度,所以即使一个处理消息的进程挂掉,加入队列中的消息仍然可以在系统恢复后被处理。
顺序保证
在大多使用场景下,数据处理的顺序都很重要。大部分消息队列本来就是排序的,并且能保证数据会按照特定的顺序来处理。Kafka保证一个Partition内的消息的有序性。
缓冲
在任何重要的系统中,都会有需要不同的处理时间的元素。例如,加载一张图片比应用过滤器花费更少的时间。消息队列通过一个缓冲层来帮助任务最高效率的执行———写入队列的处理会尽可能的快速。该缓冲有助于控制和优化数据流经过系统的速度。
冗余
有些情况下,处理数据的过程会失败。除非数据被持久化,否则将造成丢失。消息队列把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据丢失风险。许多消息队列所采用的"插入-获取-删 除"范式中,在把一个消息从队列中删除之前,需要你的处理系统明确的指出该消息已经被处理完毕,从 而确保你的数据被安全的保存直到你使用完毕。
异步通信
很多时候,用户不想也不需要立即处理消息。消息队列提供了异步处理机制,允许用户把一个消息放入队列,但并不立即处理它。想向队列中放入多少消息就放多少,然后在需要的时候再去处理它们。
Kafka系统架构
Broker
- kafka集群包含一个或多个服务器,服务器的节点被称为Broker
- Broker存储Topic的数据 ,如果某topic有N个partition,集群有N个broker,那么每个broker存储该topic的一个partition。
如果某topic有N个partition,集群有(N+M)个broker,那么其中有N个broker存储该topic的一个partition,剩下的M个broker不存储该topic的partition数据。 - 如果某topic有N个partition,集群中broker数目少于N个,那么一个broker存储该topic的一个或多个partition。在实际生产环境中,尽量避免这种情况的发生,这种情况容易导致Kafka集群数据不均衡。
Topic
- 每条发布到Kafka集群的消息都有一个类别,这个类别被称为Topic。
- 类似于数据库的table或者ES的Index
- 物理上不同Topic的消息分开存储
-
逻辑上一个 Topic 的消息虽然保存于一个或多个 broker 上但用户只需指定消息的 Topic 即可生产或消费数据而不必关心数据存于何处)
-
创建流程:1.controller 在 ZooKeeper 的 /brokers/topics 节点上注册 watcher ,当 topic 被创建,则controller 会通过 watch 得到该 topic 的 partition/replica 分配。2.controller 从 /brokers/ids 读取当前所有可用的 broker 列表,对于 set_p 中的每一个partition :2.1 从分配给该 partition 的所有 replica (称为 AR )中任选一个可用的 broker 作为新的leader ,并将 AR 设置为新的 ISR2.2 将新的 leader 和 ISR 写入 /brokers/topics/[topic]/partitions/[partition]/state3.controller 通过 RPC 向相关的 broker 发送 LeaderAndISRRequest 。删除流程1.controller 在 zooKeeper 的 /brokers/topics 节点上注册 watcher ,当 topic 被删除,则controller 会通过 watch 得到该 topic 的 partition/replica 分配。2. 若 delete.topic.enable=false ,结束;否则 controller 注册在 /admin/delete_topics 上的 watch 被 fire , controller 通过回调向对应的 broker 发送 StopReplicaRequest 。
Partition
- topic中的数据分割为一个或多个partition。
- 每个topic至少有一个partition,当生产者产生数据的时候,根据分配策略,选择分区,然后将消息追加 到指定的分区的末尾(队列)
每个 partition 中的数据使用多个 segment 文件存储。 partition 中的数据是有序的,不同 partition 间的数据丢失了数据的顺序- patition的路由规则:
1. 指定了 patition ,则直接使用;2. 未指定 patition 但指定 key ,通过对 key 的 value 进行 hash 选出一个 patition3. patition 和 key 都未指定,使用轮询选出一个 patition 。 每条消息都会有一个自增的编号
- 标识顺序
- 用于标识消息的偏移量
- 每个Partition都有自己独立的编号
- 如果topic有多个partition,消费数据时就不能保证数据的顺序。严格保证消息的消费顺序的场景下,需要将partition数目设为1。
Leader
每个 partition 有多个副本,其中有且仅有一个作为 Leader , Leader 是当前负责数据的读写的partition 。1. producer 先从 zookeeper 的 "/brokers/.../state" 节点找到该 partition 的leader2. producer 将消息发送给该 leader3. leader 将消息写入本地 log4. followers 从 leader pull 消息,写入本地 log 后 leader 发送 ACK5. leader 收到所有 ISR 中的 replica 的 ACK 后,增加 HW ( high watermark ,最后commit 的 offset ) 并向 producer 发送 ACK
Follower
- Follower跟随Leader,所有写请求都通过Leader路由,数据变更会广播给所有Follower, Follower与Leader保持数据同步。
- 如果Leader失效,则从Follower中选举出一个新的Leader。
- 当Follower挂掉、卡住或者同步太慢,leader会把这个follower从“in sync replicas”(ISR)列表中删除,重新创建一个Follower。
replication
- 数据会存放到topic的partation中,但是有可能分区会损坏
- 我们需要对分区的数据进行备份(备份多少取决于你对数据的重视程度)
- 我们将分区的分为Leader(1)和Follower(N)
Leader 负责写入和读取数据 保证了数据的一致性 Follower 只负责备份备份数设置为 N ,表示主 + 备 =N( 参考 HDFS)## Kafka 分配 Replica 的算法如下1. 将所有 broker (假设共 n 个 broker )和待分配的 partition 排序2. 将第 i 个 partition 分配到第( i mod n )个 broker 上3. 将第 i 个 partition 的第 j 个 replica 分配到第( (i + j) mode n )个 broker上
producer
- 生产者即数据的发布者,该角色将消息发布到Kafka的topic中。
- broker接收到生产者发送的消息后,broker将该消息追加到当前用于追加数据的segment文件中。
- 生产者发送的消息,存储到一个partition中,生产者也可以指定数据存储的partition。
consumer
消费者可以从
broker
中读取数据。消费者可以消费多个
topic
中的数据。
Consumer Group
- 每个Consumer属于一个特定的Consumer Group(可为每个Consumer指定group name,若不 指定group name则属于默认的group)。
-
将多个消费者集中到一起去处理某一个 Topic 的数据,可以更快的提高数据的消费能力
-
整个消费者组共享一组偏移量 ( 防止数据被重复读取 ) ,因为一个 Topic 有多个分区
offset偏移量
- 可以唯一的标识一条消息
- 偏移量决定读取数据的位置,不会有线程安全的问题,消费者通过偏移量来决定下次读取的消息
- 消息被消费之后,并不被马上删除,这样多个业务就可以重复使用kafka的消息
- 我们某一个业务也可以通过修改偏移量达到重新读取消息的目的,偏移量由用户控制
- 消息最终还是会被删除的,默认生命周期为1周(7*24小时)
Zookeeper
kafka 通过 zookeeper 来存储集群的 meta 信息
、