消息队列介绍、Kafka系统架构和原理

93 阅读6分钟

为什么需要消息系统

  • 解耦
    • 业务逻辑更简单 中间件替换成本低
  • 冗余
  • 扩展性
    • 不需要考虑 扩展性问题 例如后端处理负载高的问题
  • 灵活性 & 峰值处理能力
  • 可恢复性 可以备份恢复消息
  • 顺序保证
  • 缓冲
  • 异步处理
  • 消息通信

image.png

不同的订阅端 消费不同的主题

针对不同的业务 进行适配

  • 离线业务 离线处理
  • 在线数据流

消息系统

现在比较流行的MQ有:ActiveMQ、Kafka、RabbitMQ、Redis、Jafka、ZeroMQ

image.png

Kafka 兼具消息队列 和日志聚合的场景

RabbitMQ

  • RabbitMQ是使用Erlang编写的一个开源的消息队列,本身支持很多的协议:
    • AMQP、XMPP、SMTP、STOMP,也正因如此,它非常重量级,更适合于企业级的开发。
  • 同时实现了Broker构架,这意味着消息在发送给客户端时先在中心队列排队。
  • 对路由、负载均衡或者数据持久化都有很好的支持

ZeroMQ

• ZeroMQ号称最快的消息队列系统,尤其针对大吞吐量的需求场景。

• ZeroMQ能够实现RabbitMQ不擅长的高级/复杂的队列,但是开发人员需要自己组合多种技术框架。

• 但是ZeroMQ仅提供非持久性的队列,也就是说如果宕机,数据将会丢失。

ActiveMQ

• ActiveMQ是Apache下的一个子项目。 类似于ZeroMQ,它能够以代理人和点对点的技术实现队列。

• 同时类似于RabbitMQ,它少量代码就可以高效地实现高级应用场景

生产者/消费者模型

在生产者/消费者模型中,生产者Producer负责生产数据,而消费者Consumer负责

使用数据。多个生产者会在同一时间生产数据,并放到内存中一个共享的区域

Kafka系统架构和原理

image.png

Topics 、Append Log

  • Kafka提供的一个抽象的 主题概念:topic
  • 一个topic是对一组消息的归纳 其实对应一个业务流
  • 每个topic将被分成多个partition 分区
  • 每个partition会生成一个append log文件
  • 每条消息在文件中的位置称为offset(偏移量),唯一标记一条消息

Producer和Consumer

两个API 录入数据 消费数据

image.png

  • Producer即生产者,向Kafka集群发送消息,消息会安装Topic进行分类

  • Consumer即消费者,消费者通过与Kafka集群建立长连接的方式,不断地从集群中拉取消息,然后可以对这些消息进行处理

    • 它需要保存消费消息的offset:当consumer正常消费消息时,offset将会“线性”的增加,即消息将依次顺序被消费
    • 通过设置offset consumer可以从任意位置消费消息
  • Consumer可以在本地保存最后消息的offset,并向ZooKeeper注册offset

Consumer Group

image.png

这是Kafka用来实现一个topic消息广播的手段。即多个不同的group来同时消费同一个topic下的消息。他们消费的offset各不相同,各不干扰。 实现了隔离性

一个group中,Consumer的数量不应该多于Partition的数量,即一个消费者可以消费多个分区,但一个分区只能给一个消费者消费。

注意 若一个group中的消费者数量大于Partition数量的话,多余的消费者将不会收到任何消息

  • 例如partition只有3个 但是consumer有4个 所以至少有一个是拿不到数据的

约束

同一个Consumer Group 一个Partition只能对应一个Consumer 但是一个Consumer 可以对应多个Partition

Broker

image.png

消息保存在一组服务器中,它们被称为代理(Broker)或Kafka集群

  • 每个Broker有一个Broker id
  • 每个Broker存储Topic的部分数据

Kafka的存储文件

按照offset.kafka来命名,用offset做名字的好处是方便查找。

例如 你想找位于2049的位置,只要找到2048.kafka的文件即可。第一个个存储文件是00000000000.kafka

整体架构图

image.png 一个topic可以划分 多个 partition切片

  • 每个partition切片 可以 复制多个 replica副本
  • 每个replica副本 分布在不同的节点
  • replica副本 之间有主从之分 leader和follower(主从关系)

ZK的作用

  1. 当Consumer Group 挂掉时, 需要保存已经消费的offset 不然恢复后怎么办?

commit offset操作 将offset记录到ZK中

  1. ZK 还要记录集群状态信息 leader和follower(主从关系)

replica副本

0.8版本后 加入了 replica副本

类似主动复制 写的时候 只写 leader 然后会把数据同步到follower 读的时候 leader和follower

Kafka将每个partition数据复制到多个server上,任何一个partition有一个leader和零个或多个follower(ISR),称为partition的副本(replica)。

Leader处理所有的读写请求,follower需要和leader保持同步。Follower和consumer一样,消费消息并保存在本地日志中

当所有的follower都将一条消息保存成功,此消息才被认为是“committed”。只有committed的消息,consumer才能消费它。

问题 当leader失效时,需在followers中选取出新的leader。可能此时follower落后于leader,因此需要选择一个尽可能“新”的follower

消费传输机制

生产者发送消息到 kafka时 会有2阶段提交问题

先保存offset 还是 先处理消息, 任何一个地方出现问题 都会导致丢数据 或者 数据重复消费的问题

at most once

消息最多发生一次,无论消费者是否接受到,都不会重发。

消费者fetch消息,先保存消息的offset,然后处理消息。

问题 当消费者保 存offset之后,但是在消息处理过程中出现了异常,导致部分消息未能继续处理。

那么此后“未处理”的消息将不能被fetch到,这就是“at most once”。

at least once

消息至少发送一次,如果消息未能接受成功,会重发直到接收成功。

消费者fetch消息,先处理消息,然后保存offset。

问题 如果消息处理成功之后,但是在保存offset阶段,ZooKeeper异常导致保存操作未能执行成功,这就导致接下来再次fetch时可能获得上次已经处理过的消息,这就是“at least once”。

exactly once

消息只会发送一次。

容灾

多副本机制可以保证数据 可用

如果宕机节点上的replica是leader 那么就会重新选举 尽可能新的leader image.png