消息队列小结

为啥要使用消息队列,主要是两个目的:
(场景:生产者消费者模型)

  1. 生产者与消费者速度不匹配;(生产者太快了)
  2. 解耦生产者与消费者。(可以异构,不同语言,不同节点)

JMS(Java MessageService)

Sun公司早期提出的消息标准。
api规范(旧).支持点对点和发布订阅.

概念 解释
producer/publisher 生产者
consumer/subscriber 消费者
message 消息
queue 存放消息的地方
topic 提供多个订阅者消费消息的机制

JMS中的消息模式有两种:

  1. P2P: 点对点
  2. publish-subscribe: 发布订阅

AMQP (advanced message queuing protocol)

高级MQ协议. 不但约束了api,还使不同实现之间可以合作.
加入了Exchange,Binding,解耦了队列,
可以灵活实现除了点对点\发布订阅以外的模型.
消息模型:

AMPQ其中一个实现: rabbitmq

简单理解概念:

1
2
3
4
Channel : 信道.一个连接多个Channel. 节省开销.(复用tcp连接,每次发送消息算一个信道)
Exchange: 交换器、路由器.
Queue: 队列. 带名字的邮箱.
Binding: 绑定.// 路由规则

Exchange:
根据配置好的路由规则,转发收到的消息到符合的queue.
不同类型的exchange:

1
2
3
4
direct 直连
fanout 一个消息到多个队列
topic 多个消息到一个队列
header // 不实用,即将弃用

kafka

基本概念

1
2
3
4
5
6
7
Broker: kafka server的一个单位(brokerid);
Topic: 某个主题;
Partition: 一般对应磁盘个数,加大吞吐率;
Replica: 0.8后新增,高可用;(3/5...)
Consumer
Group: 管理多个consumer
Producer

内部组件

1
2
3
4
5
6
SocketServer: 接受消息,返回消息(客户端、内部通信),
RequestHandlerPool: 根据不同request类型,调用不同KafkaApi处理消息
KafkaApi
KafkaController->ReplicaStateManager+PartitionStateManager+Listener
ReplicaManager: 底层存储结构,每个broker上都有。接受读写操作。
Zookeeper:1. 发现服务,状态转移;2. 存储offeset。(1.0后转入topic)

KafkaController

Broker通过ZK抢注Controller。
Controller负责管理broker。它会注册很多Listener,监听zk上节点变化,来维护状态自动机变化。

  • 防止脑裂:
    旧controller epoch<新controller epoch

    Follower与Leader

    Follower与Leader均是针对某一个partition而言:
  1. Slave(Follower,对于某一个topic的partition是follower):同步数据。
  2. Slave(Leader,对于某一个topic的partition是leader): 接受kafkaApi(consumer和producer)的请求。

读写partition:
随机找一个机器->metadata(zk)->发送请求给这个partition的具体leader。

SocketServer

状态机

KafkaHA

ISR: in-sync Replica
leader: 最新offset;
follower: 最新offset就是ISR;(轮询offset)
zk: 都有谁是ISR,同步了。

leader挂了,选一个ISR;
如果没有ISR,则随机选一个最先起来的。(不一定选offset最高的,不确定后头还会不会起来follower)。

ACK(均到内存,均不保证落盘)
1: leader收到就收到;
2: 有一个follower收到就收到;
3: 所有follower收到才收到。

错误恢复

  • leader选举
    直接从ISR中选第一个(近似于随机)。

  • Controller选举:(某台机器)
    所有Broker抢注ZK。

Controller挂的时候: 所有replica和partition的状态不能改变。也不能reBanlance了。
如果Controller挂的时候,leader也挂,所在partition就不能读不能写了。

  • 倾斜(热点):
    一台最稳定的机器上,可能集中了所有leader.
    (可以手动reAssign)

实际案例

其他类kafka的消息队列改进:

  1. Consumer之间消费的分区互不重叠(防止kafka的重复消费);(tube)
  2. 严格有序:数据落地到单队列上,每次ACK。(hippo)
  3. controller改成双master热备,降低对zk依赖,引入nameserver.(rocketmq)

推荐文章