消息队列MQ

消息队列理论

作用

  1. 流量削峰:削峰填谷
  2. 异步处理:将同步请求转换为异步,并且请求放入队列后,可以有多个消费者消费,提升整体的响应时间
  3. 服务解耦:服务方只需要把消息放入消息队列,下游谁需要就由谁订阅,下游系统的增减,不影响服务方。(openStack整个服务间的交互全都采用mq,默认rabbitMq)

基本概念

两种模型

  1. 队列模型(Quene):一个队列可以有多个生产者和消费者。但消费者之间是竞争关系,每条消息只能被一个消费者所消费。RabbitMq采用队列的方式解决一条消息被多个消费者接收,是通过Exchange模块将消息发送至多个队列
  2. 主题模型(Topic,发布/订阅模型):生产者将消息发往一个topic主题中,所有订阅了这个topic的订阅者都能消费这条消息。RabbitMq采用队列模型,RocketMq和kafka采用发布订阅模型,activeMq支持两种模型

producer/broker/consumer

mq三个角色

  • 为了提高并发度,Topic模式往往还会引入队列或者分区的概念,即消息发往Topic下的某个队列或分区中。RocketMq叫队列,kafka中叫分区。如某个Topic有5个队列,那么该主题的并发度就提高为5,可以有五个消费者并行消费该主题的消息。一般可以采用轮询或者hash取余的方式将消息分配到不同的队列当中
    消费者组
  • 为了提高消费者的并发度,消费者通常都有消费者组(consumer group)的概念,消费者都是属于某个消费者组的。一个消息会发往多个订阅了这个topic的消费者组。这个消息实际上是写到了topic下的某个队列中,消费者组中的某个消费者对应消费一个队列的消息,同一消费者组下的应用,可以认为是同一应用的集群,一个topic下的一个队列,只会对应消费组下的一个实例(或一个线程),如果实例数大于队列数,则有的实例是不会分配消息的
  • 物理上一条消息处理副本拷贝以外,一条消息在broker中只会有一份,每个消费组有自己的消费点位(offset)来标识消费到的位置。offset之前的消息是被这个消费组消费过的,这个offset是队列级的,每个消费组都会维护订阅的topic下的每个队列的offset

rocketmq offset的维护

[参考文章](https://blog.csdn.net/agonie201218/article/details/120242146)

  • **本地管理模式:**消费者广播模式下,每个消费者将消费点位以json的方式存储在本地文件中,每个消费者管理自己的消费点位,各消费者间不存在消费进度的交集
  • **远程管理模式:**消费者集群消费模式下,topic下每个quene的消费点位以json文件的方式持久化在broker的本地文件中,broker内存中会形成一个双层map,[topic, [queneId, offset]]。正常情况下topic下的一个quene只会被一个消费者消费,使用远程管理的模式,主要是为保证rebalance的机制
  • 消费者启动时,要消费的第一条消息的起始位置有三种:1. CONSUME_FROM_LAST_OFFSET从queue的当前最后一条消息开始消费;2. CONSUME_FROM_FIRST_OFFSET从queue的第一条消息开始消费;3.CONSUME_FROM_TIMESTAMP从指定的具体时间戳位置的消息开始消费。
  • offset提交broker支持同步和异步的方式,同步提交offset时,会等待broker响应后再进行下一条消息的消费;异步提交offset时,不用等待就继续消费消息。默认异步提交的方式,但如果发生rebance,则因为消费者消费的消息offset可能大于broker存的offsetid,下一个消费者会从broker 存储的offset的位置继续消费,可能会有消息重复消费的问题

怎么保证消息不丢失

消息处理过程

  1. 生产者:可靠消息,本地消息表与本地事务同一个线程,消息表记录消息发送状态,失败定时重试
  2. broker:刷盘后,或者至少有两个节点都写入成功后再返回生产者消息发送成功
  3. 消费者:业务处理完成后再更新offset,为缩短时间可批量处理,或先做消息持久化再异步处理

处理重复消息

幂等机制: 版本号、业务流水号、业务状态等

如何保证消息有序性

  1. 全局有序: 一个topic下一个队列,性能低,实际诉求少。
  2. 部分有序: 一个topic下多个队列,可以按照一定的规则,把需要局部保持顺序的消息路由到一个队列,由一个消费者消费。生产者自定义消息发往topic下某个quene的规则

处理消息堆积

原因: 生产者的生产速率与消费者的消费速率不匹配
优化:1. 优化消费者的处理性能;2. 增加topic队列和消费者数量,即水平扩容,注意一个topic下的队列只会分配给一个消费者。

rocketMq消息消费

RocketMq 消费者pull消息

  • 消费者和broker的消息获取,有推拉两种模式,activeMq用推的模式。RocketMq和kafka均采用拉的模式,通过长轮询的方式,通过消费者等待消息,当有消息时broker会直接返回消息,如果没有消息,则会采用延迟处理的方式,并且为了保证消息实时性,当有新消息到来时,会及时返回消息
  • rocketMq消费者和broker间TCP长连接。

RocketMq事务消息

rocketMq事务消息

  • rocketmq事务消息事务开始时小发起一个半消息,本地事务执行后,根据执行结果发送消息的提交或者回滚,半消息对消费者是不可见的,消息提交后才放入正常队列供消费者消费。
  • 生产者发送的提交或回滚有可能会失败,因此需要producer暴露一个接口,供broker定时查询事务状态。

RocketMq

原理

参考文章

特点

  1. 吞吐量高:单机吞吐量可达十万级
  2. 可用性高:分布式架构
  3. 消息可靠性高:经过参数优化配置,可以做到消息零丢失
  4. 功能较为完善,分布式架构易于扩展
  5. 支持10亿级别的消息堆积,不会因为堆积导致性能下降
  6. 稳定性高,经过阿里双11考验
  7. Java语言实现

部署

rocketMq集群架构
RocketMq由四部分构成:Producer、Consumer、Broker、NameServer

  • producer(生产者):可集群部署,先与nameServer中的一台建立长链接,获取当前要发送的topic存放在哪个Broker Master上,再与其建立长连接,支持多种负载均衡模式发送消息。producer会与满足条件的多个broker建立长连接,轮询他们来发送消息,同步发送消息失败的情况下,默认(retryTimesWhenSendFailed = 2)会重试其他节点两次,异步发送失败也会重试两次(retryTimesWhenSendAsyncFailed = 2),但只会重试当前失败的节点。
  • consumer(消费者):可集群部署,也会先与nameServer中的一台建立长链接,获取当前要的消息topic存放在哪个Broker master 、slaver上,然后与他们建立长连接,支持集群消费和广播消费。消息消费失败,rocketmq会给每个消费者组设置一个重试队列,%retry%+consumerGroup,设置了很多重试级别来延迟重试时间。超过一定重试次数都失败,会移入死信队列Topic %DLQ%" + ConsumerGroup,人工处理死信队列里的消息
  • Broker: 负责消息的存储、查询消费,支持主从部署,一个master对应多个slave,master支持读写,slave只支持读。**broker会向集群中的每一台nameServer注册自己的路由信息。**生产上不建议开启自动创建主题的配置,可能会导致消息发送不均衡。多Master多Slave模式,同步双写部署模式,会避免丢消息
  • nameServer: 是一个简单的Topic路由注册中心,支持Broker的动态注册发现,保存Topic和Broker的关系。通常也集群部署,但各nameServer间不会相互通信,每个nameServer都有完整的路由信息,即无状态维护集群中存活的broker列表,broker信息,主题和队列信息

工作过程:
先启动nameServer集群,各nameServer间不会有信息交互。Broker启动后,会向所有nameServer定时发送心跳包(默认30s),包括:ip/port/topicInfo,nameServer会定期扫描broker存活列表,如果超过120s没有心跳,则移除此broker信息,代表下线。
每个nameServer就知道集群中所有broker的信息,producer上线,从某个nameserver中可以得知他要发送的topic位于哪个broker上,与对应broker(master角色)建立长连接,发送消息。
consumer也从nameserver中获取broker master 、slave的信息,并与他们建立长连接,接收消息
使用建议:一个生产者应用集群使用一个Topic(生产者只关注消息生产,而不关心由谁来消费消息,消费者的增减对生产者无感),通过tags标记业务类型。不同的消费者设置不同的消费者组,对于不是当前消费者能消费的消息,跳过即可

RocketMq性能高的原因:RocketMq采用文件系统存储消息,采用顺序写的方式写入消息,使用零拷贝发送消息,这三者的结合极大地保证了RocketMq的性能

RocketMq消息清理

参考文章

  • Broker消息被顺序写入commitLog文件,清理不是以消息的粒度来清理的(消息大小不定,文件顺序写,按消息级清理性能低),而是commitLog文件为单位进行清理
  • 清理commitLog文件,可以手工清理,或者满足一定条件下自动清理(commitlog文件存在一个过期时间,默认为72小时,即三天):
  1. 文件过期,到达清理时间点(默认凌晨4点)
  2. 文件过期,磁盘占用率已达过期清理警戒线(默认75%)
  3. 磁盘占用率达清理警戒线(默认85%),按预定规则清理文件,无论是否过期。默认会从最老的文件开始清理
  4. 磁盘占用率达到系统危险警戒线(默认90%)后,Broker将拒绝消息写入
  • 对于RocketMQ系统来说,删除一个1G大小的文件,是一个压力巨大的IO操作。在删除过程中,系统性能会骤然下降。默认在访问量最小的时候删除;我们应保障磁盘空间的空闲率,不要使系统出现在其它时间点删除commitlog文件的情况。建议linux文件系统采用ext4(删除操作ext4比ext3高)

rocketMq高可用部署

4种高可用部署方法
推荐:
rocketMq基于** Dledger **的高可用部署方案,每个master对应两个slave(三台组成一个Dledger Group),主宕机两个从可以基于raft算法自动选主切换。

Dledger高可用部署方案
四种高可用部署方案分别为:

  • 多master
  • 多Master多Slave模式-异步复制
  • 多Master多Slave模式-同步双写
  • Dledger部署

rabbitMq

参考文章
镜像集群模式

kafka

kafka的客户端身份认证机制

  • SASL(Simple Authentication and Security Layer)提供一种用户身份认证机制。参考文章
  • kafka支持的认证方式很多,支持SSL或者SASL,下面四种SASL认证方式是官方支持的。参考文章
    kafka支持的四种SASL方式

kafaka配置SASL/SCRAM安全认证

  1. 创建SCRAM证书
    • broker通信账户:
./kafka-configs.sh --zookeeper localhost:2181 --alter --add-config 'SCRAM-SHA-256=[password=admin-sec],SCRAM-SHA-512=[password=admin-sec]' --entity-type users --entity-name admin
* 客户端通信用户(生产者和消费者共用,可分开)
./kafka-configs.sh --zookeeper localhost:2181 --alter --add-config 'SCRAM-SHA-512=[password=password]' --entity-type users --entity-name app
* 证书查看和维护
# 查看
./kafka-configs.sh --zookeeper localhost:2181 --describe --entity-type users --entity-name app

# 删除
./kafka-configs.sh --zookeeper localhost:2181 --alter --delete-config 'SCRAM-SHA-512' --entity-type users --entity-name app
  1. 服务端(broker)配置
    • 新增kafka_server_jaas.conf
KafkaServer {
org.apache.kafka.common.security.scram.ScramLoginModule required
username="admin"
password="admin-sec";
};
* broker启动脚本kafka-server-start-saal.sh(copy from kafka-server-start.sh)
# 启动脚本添加认证文件配置
exec $base_dir/kafka-run-class.sh $EXTRA_ARGS -Djava.security.auth.login.config=/opt/kafka/kafka_2.13-3.6.0/config/kafka_server_jaas.conf kafka.Kafka "$@"
* 配置server-sasl.properties (copy from server.properties)
#认证配置
listeners=SASL_PLAINTEXT://192.168.195.129:9092
security.inter.broker.protocol=SASL_PLAINTEXT
sasl.mechanism.inter.broker.protocol=SCRAM-SHA-512
sasl.enabled.mechanisms=SCRAM-SHA-512
#ACL配置
# 黑名单模式,特殊指定的名单是不允许访问的名单,没指定的是可以访问的;配置为false为白名单模式,即需要还给用户分配topic的发送和接收权限
allow.everyone.if.no.acl.found=true
super.users=User:admin
# authorizer.class.name=kafka.security.auth.SimpleAclAuthorizer
* 启动kafka broker
./bin/kafka-server-start-saal.sh ./config/server-sasl.properties
  1. 客户端配置(包含admin/producer/consumer)
    • admin配置:kafka_client_scram_admin_jaas.conf
KafkaClient { org.apache.kafka.common.security.scram.ScramLoginModule required username="admin" password="admin-sec"; };
* producer/consumer配置:kafka_client_scram_client_jaas.conf
KafkaClient { org.apache.kafka.common.security.scram.ScramLoginModule required username="app" password="passw0rd"; };
* producer/consumer启动脚本sh:kafka-console-producer-saal.sh(copy from kafka-console-producer.sh);kafka-console-consumer-saal.sh(copy from kafka-console-consumer.sh)
# 启动脚本添加参数
-Djava.security.auth.login.config=/opt/kafka/kafka_2.13-3.6.0/config/kafka_client_scram_client_jaas.conf
* consumer-saal.properties和producer-saal.properties (copy from consumer.properties/producer.properties)
# 要追加的配置项目
security.protocol=SASL_PLAINTEXT
sasl.mechanism=SCRAM-SHA-512
* 命令行版本的producer/consumer 使用
# 生产者命令行
./kafka-console-producer-saal.sh --broker-list localhost:9092 --topic test --producer.config ../config/producer-saal.properties
# 消费者命令行
./kafka-console-consumer-saal.sh --bootstrap-server localhost:9092 --topic test --from-beginning --consumer.config ../config/consumer-saal.properties
* java 连接kafka,通过SCRAM模式

producer
Consumer

常见消息队列对比

参考文章
四种常见mq对比

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值