深入原理64式:31 rabbitmq知识总结

目标:
整理rabbitmq知识,主要包含如下内容:
1、基础
2、集群
3、综合
4、数据丢失
5、原理

一 基础


1 RabbitMQ 中的 broker 是指什么?cluster 又是指什么?
1)broker是erlang node逻辑分组,node上运行rabbitmq应用
2)cluster是在broker基础上,增加node之间共享元数据的约束

2 什么是元数据?元数据分为哪些类型?包括哪些内容?与 cluster 相关的元数据有哪些?元数据是如何保存的?元数据在 cluster 中是如何分布的?
1)非cluster模式下,元数据主要包含:Queue/Exchange/Binding(存放路由关系的查找表)/Vhost(
针对Queue,Exchange,Binding的名字空间约束和安全属性设置)。
2)cluster模式下,还包括node位置和关系信息。
3)元数据根据erlang node的类型确定是仅仅保存于RAM中还是同时保存于RAM和disk上。
4)元数据在cluster中是全node分布的。

3 RAM node 和 disk node 的区别?
RAM node仅仅将queue,exchange,binding等相关元数据保存在内存中,
disk node会同时在内存和磁盘中存储。
RAM node会将disk node地址存储到磁盘的元数据。
要求集群中至少有一个磁盘节点,当有节点加入和离开集群时,必须通知磁盘节点。


4 RabbitMQ 上的一个 queue 中存放的 message 是否有数量限制?
默认无限制,实际收到机器内存等因素限制。

5 RabbitMQ 概念里的 channel、exchange 和 queue 这些是逻辑概念,还是对应着进程实体?这些分别起什么作用?
1)queue有自己的erlang进程;
exchange保存binding关系的查找表;
channel是实际进行路由工作的实体,根据routing_key将消息投递给queue。
2)channel是在tcp连接上的虚拟链接,amqp命令通过channel发送,
一个线程允许使用多个channe,多线程共享同一个socket。
channel复用模型如下:
frames    frames    framses
channel    channel    channel
    socket

6 vhost是什么?起什么作用?
1) 是虚拟broker,即mini-rabbitmq服务器,含有独立的queue,exchange,binding等,
有独立权限系统。
2) vhost可以进行权限隔离。不同应用可以跑在不同vhost中。

7 使用RabbitMQ有什么好处?有什么缺点?什么是rabbitmq?
1)
解耦,各个服务之间解耦,多进程数据交换
异步,消息写入队列,业务异步处理。
削峰,高负载任务负载均衡,例如点上秒杀。可以从MQ中慢慢拉去请求给数据库处理,
防止数据库崩溃。
2)系统可用性和复杂性增加。
3)采用AMQP高级消息队列协议的消息队列技术,消费并不需要确保提供放存在,
实现服务解耦。

8 消息基于什么传输?
由于tcp连接的创建和销毁开销大,使用channel信道方式传输数据。
信道是建立在tcp连接上的虚拟链接,每个tcp链接上的信道数量没有限制。

9 消息如何分发?
轮询: 若该队列有消费者订阅,消息以round-robin方式发送给消费者,每条消息只会发送给一个消费者。
公平分发: 设置prefetch_count表示有多少消息没有ack就不再发送消息给这个消费者


10 消息怎么路由?
消息消费者会将exchange通过binding_key绑定对应的队列,
消息生产者发送消息的时候会指定exchange和routing_key,
消息到达交换器后,会将消息的路由键和队列的binding_key进行匹配,
若能够匹配到队列,则消息投递到队列中。

11 常见交换器有哪些?
direct:若路由键完全匹配,消息投递到相应队列
fanout:交换器接受到消息,会广播到所有绑定的队列上
topic: 可以使用*匹配特定位置字符,#陪陪所有规则。键鼻息是"."隔开的标识符。


12 什么是死信队列?什么是死信交换器?什么是死信消息?什么是过期消息?什么是延迟队列?
1)死信交换器在消息变成死信后,若消息所在队列存在x-dead-letter-exchange
,消息会被发送到x-delad-letter-exchange对应的交换器上,该交换器就是死信交换器,
2)与死信交换器绑定的就是死信队列。
3)消息被拒绝并且设置requeue为false,消息过期,队列达到最大长度后先入队的消息。
4)可以设置队列x-message-ttl(毫秒),所有消息在相同时间过期;为消息单独设置过期时间expiration(毫秒)。
消息过期后变成死信消息。
5)延迟队列,不存在,但是可以通过设置消息过期时间和死信队列模拟。
消费者监听死信交换器绑定的队列而不需要监听消息发送的队列。
TTL + 死信交换机 + 先保存消息到数据库,用调度起扫描发送。

 

13 如何确保消息接收方消费了消息?
接收方有确认机制:消费者接收每一条消息后都必须进行确认,只有确认后,才会将消息从队列删除。
消费者接受消息后,在确认之前断开链接,会重新分发消息给下一个消费者。
消费者收到消息没有确认,连接也没有断开,则认为消费者繁忙,不会给该消费者
发送更多消息。

14 如何避免消息重复投递或重复消费?
MQ内部给每条消息生成inner-msg-id麻痹面重复消息进入队列;消息消费时要求有对应id。
1)若数据库插入操作,给消息设置主键,重复消费会导致主键虫害图
2)redis的set,set操作冪等
3)用其他记录消费历史,将<id, message>写入redis,消息消费前查询是否有消费记录。

15 无法被路由的消息,去了哪里?
丢弃。解决方法:
指定备份交换机,设置mandatory=true配置ReturnListener实现消息回发。

16 如何保证消息的可靠性投递?
1)保证投递到服务端的broker上/正确路由
2)持久化存储
3)消费者应答/回调

17 什么是消息幂等性?
冪等性是指一次和多次请求同一个资源应该具有同样的结果。
生产者为每条消息生成一个msgId,防止重复投递;
消费者消费消息时,确保消息中携带业务id,例如支持id,防止重复消费。

18 如何在服务端和消费端做限流?
网关/接入层:限流
服务端(Broker):对内存和磁盘控制
消费者: prefetch_count。

19 如何保证消息的顺序性?
通过全局id实现。
每条消息有msgId,关联消息有同一个parentMsgId,
可以在消费端实现前一条消息未消费,不处理吓一跳消息。

20 如何解决消息队列的延时以及过期失效问题?
监控可堆积消息数来预警,重启消费者,增加消费者进程。

21 如何确保消息不丢失?
消息,交换器,队列都持久化。
重启恢复方式:
写入磁盘上的持久化日志文件,会在提交到日志文件
后才发送相应,一旦消费消息,在日志中将该消息标记
为等待垃圾收集。
若消息被消费前重启,则重建交换器和队列(以及绑定),
重新发布持久化日志文件中的消息到队列。

22 如何指定消息的优先级?
设置队列的max priority参数,rabbitmq中消息默认优先级是0,最大值是10


23 rabbitmq中基本概念?
AMQP,即Advanced Message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。
Broker(Server):接受客户端连接,实现AMQP消息队列和路由功能的进程。
Virtual Host:其实是一个虚拟概念,类似于权限控制组,一个Virtual Host里面可以有若干个Exchange和Queue,但是权限控制的最小粒度是Virtual Host。
Exchange:接受生产者发送的消息,并根据Binding规则将消息路由给服务器中的队列。ExchangeType决定了Exchange路由消息的行为,例如,在RabbitMQ中,ExchangeType有direct、Fanout和Topic三种,不同类型的Exchange路由的行为是不一样的。
广播式交换器类型(Fanout)
该类交换器不分析所接收到消息中的 Routing Key,默认将消息转发到所有与该交换器绑定的队列中去。
直接式交换器类型(Direct)
该类交换器需要精确匹配 Routing Key 与 Binding Key,如消息的 Routing Key = Cloud,那么该条消息只能被转发至 Binding Key = Cloud 的消息队列中去。
主题式交换器(Topic Exchange)
该类交换器通过消息的 Routing Key 与 Binding Key 的模式匹配,将消息转发至所有符合绑定规则的队列中。
Binding Key 支持通配符,其中“*”匹配一个词组,“#”匹配多个词组(包括零个)。

Message Queue:消息队列,用于存储还未被消费者消费的消息。
Message:由Header和Body组成,Header是由生产者添加的各种属性的集合,包括Message是否被持久化、由哪个Message Queue接受、优先级是多少等。而Body是真正需要传输的APP数据。
Binding:Binding联系了Exchange与Message Queue。Exchange在与多个Message Queue发生Binding后会生成一张路由表,路由表中存储着Message Queue所需消息的限制条件即Binding Key。当Exchange收到Message时会解析其Header得到Routing Key,Exchange根据Routing Key与Exchange Type将Message路由到Message Queue。

Binding Key由Consumer在Binding Exchange与Message Queue时指定,而Routing Key由Producer发送Message时指定,两者的匹配方式由Exchange Type决定。
Connection:连接,对于RabbitMQ而言,其实就是一个位于客户端和Broker之间的TCP连接。
Channel:信道,仅仅创建了客户端到Broker之间的连接后,客户端还是不能发送消息的。需要为每一个Connection创建Channel,AMQP协议规定只有通过Channel才能执行AMQP的命令。一个Connection可以包含多个Channel。之所以需要Channel,是因为TCP连接的建立和释放都是十分昂贵的


二、集群


1 在单 node 系统和多 node 构成的 cluster 系统中声明 queue、exchange ,以及进行 binding 会有什么不同?
单节点声明queue只需要该节点元数据更新就会得到Queue.Declare-ok;
集群上声明queue需要所有node元数据更新成功得到Queue.Declare-ok;
若node类型为RAM,则变更仅仅保存在内存中;
若node类型为disk,则变更还要保存在磁盘上。


2 客户端连接到 cluster 中的任意 node 上是否都能正常工作?
是的。

3 若 cluster 中拥有某个 queue 的 owner node 失效了,且该 queue 被声明具有 durable 属性,是否能够成功从其他 node 上重新声明该 queue ?
不能,只有等到queue所属的node回复后采纳呢个使用该queue。
若queue本身不具备durable属性,则可以在其他node上重新声明。

4 cluster 中 node 的失效会对 consumer 产生什么影响?若是在 cluster 中创建了 mirrored queue ,这时 1)1)node 失效会对 consumer 产生什么影响?
若消费者链接的node失效,则消费者会在tcp连接断开时,进行重连,并重建fabric。
2)消费者只能通过Consumer Cancellation Notification机制来检测与该queue订阅关系的终止,
否则会出现等待却没有消息到来的问题。

5 能够在地理上分开的不同数据中心使用 RabbitMQ cluster 么?
不能。
原因是无法控制创建的queue分布在cluster的哪个node上,导致跨地域访问问题‘
出发超时问题;链接失效将导致脑裂。

6 RabbitMQ的集群模式和集群节点类型?
集群模式分为普通模式和镜像模式。
普通模式:
消息实体只存在于其中一个节点上,若消息持久化,需等待节点回复才可以被消费。
镜像模式:
创建的queue的元数据和消息都会存在于多个实例上,消息到queue时,
会把消息到多个实例的queue里进行消息同步。
有性能开销。

节点有两种:
内存: 保存状态到内存
磁盘节点: 保存状态到内存和磁盘。一个集群中至少需要一个磁盘节点。

7 RabbitMQ 的高可用性如何保证?
三种模式是:单击/普通集群/镜像集群
普通模式不存在高可用,多台机器启动多个rabbitmq实例,创建的queue只会放在
一个rabbitmq实例上,但是每个实例都同步queue的元数据。
消费的时候,如果连接到另外一个实例,
实例会从queue所在实例上拉取数据,若存放queue的实例崩溃,则无法拉去;若消息持久化,
则得等到这个实例恢复后,才可以继续从queue拉取数据。
镜像集群模式: 高科用,指定要求数据同步到所有节点,创建queue,会将数据同步到
其他节点。

 

三 综合


1 为什么 heavy RPC 的使用场景下不建议采用 disk node ?
heavy RPC是指高频调用Rabbitmq中RPC机制,会不断创建销毁应答队列,
造成disk node性能问题,因为会对元数据不断写盘。

2 向不存在的 exchange 发 publish 消息会发生什么?向不存在的 queue 执行 consume 动作会发生什么?
都会收到Channel.Close信令告知不存在。

3 routing_key 和 binding_key 的最大长度是多少?
255字节。

4 RabbitMQ 允许发送的 message 最大可达多大?
消息体大小由64-bit值指定。

5 什么情况下 producer 不主动创建 queue 是安全的?
1)消息允许丢失
2)对未处理消息的republish功能

6 “dead letter”queue 的用途?
消费者通过Basic.Reject拒绝消息时,会将消息放入死信队列。
该队列可以用于排查消息被拒绝或未投递的原因。

7 为什么说保证 message 被可靠持久化的条件是 queue 和 exchange 具有 durable 属性,同时 message 具有 persistent 属性才行?
binding关系表示为:
exchange-binding-queue。假如queue和exchange没有设置durable属性,
那么crash之后就无法恢复,消息无处安放,无法持久化;
若消息本身没有设置persistent属性,则消息持久化也无从弹起。

8 什么情况下会出现 blackholed 问题?
是指向exchange发送消息,但是消息丢失,发送者不知道。
原因:
1)向未绑定的queue的exchange发送消息;
2)exchange以binding_key keyA绑定queueA,但是消息的routing_key
是keyB。

9 如何防止出现 blackholed 问题?
保证相关的fabric存在(exchange,queue,binding)

10 Consumer Cancellation Notification 机制用于什么场景?
保证镜像队列中master挂掉的时候,链接到slave的消费者可以收到
自身consumer被取消的通知,进而可以重新执行consume并选出新的
master。若不采用该机制,后续无法接受新master广播出来的message。

11 Basic.Reject 的用法是什么?
消费者可以使用Basic.Reject对消息拒绝。
若设置了requeue为true,
则当Rabbitmq Server收到拒绝后,将消息发送到下一个处于consume状态
的consumer处。
若没有设置requeue为true,
则将消息从队列中移除。
Basic.Nack可以一次拒绝多条消息。

12 为什么不应该对所有的 message 都使用持久化机制?
1)性能下降,写磁盘比写RAM慢
2)message持久化带来一些问题,若message设置persistent,
队列没有设置durable,queue的owner node异常后,未重建该队列前,发送到
该队列的消息都会被blackholed;
队列设置durable,queue的owner node异常后且无法重启时,queue无法在其他node上重建。
3)应该对关键消息作持久化处理或者使用ssd进行存储。

13 RabbitMQ 中的 cluster、mirrored queue,以及 warrens 机制分别用于解决什么问题?存在哪些问题?
1)cluster是提高可用性,增加node可以增加吞吐量。
cluster无法解决跨数据中心问题(即脑裂问题)。
在cluster前使用haproxy可以进行失效node探测,并负载均衡。
2)mirrored queue是为了解决使用集群所创建的queue只存在于单一node的问题。
若想正确使用该功能,需要保证:
A) consumer支持Consumer Cancellation Notification机制
B) consumer能够处理重复消息
3)warrens是为了解决集群中消息可能被blackholed问题,即
不能接受生产者不停republish消息但是Rabbitmq无回应情况。
有两种模型:
A)两台独立的rabbitmq server + haproxy,两个server无数据共享,
serve可以基于不同版本。
若使用持久化,active的server异常,持久化该server上的消息将无法被consume。
需要感知链接断开和恢复后的能力。
B)两台共享存储的rabbitmq server + keepalived,可基于共享存储
做到完全回复,要求相同的rabbitmq版本。


四、数据丢失


1 生产者丢数据如何解决?
transaction和confirm模式保证生产者不丢失消息。
1)transaction发送消息前开启事务(channel.txSelect()),发送异常则回滚(channel.txRollback()),成功则提交事务(channel.txCommit())。
2)confirm,消息会被分配唯一id,消息匹配队列会发送ack给生产者,
否则,发送nack,可以进行重试。

2 消息队列丢数据如何解决?
开启持久化磁盘配置。可以在消息持久化到磁盘后,再给
生产者发送ack信号。
持久化的步骤:
1)queue设置durable为true
2)发送消息设置deliveryMode=2来实现消息持久化

3 消费者丢数据如何解决?
开启手动确认模式可以解决。
1)自动确认模式:消费者挂掉,待ack的消息回到队列,消息不断重发,直到处理成功。
2)手动确认模式:消费者如果处理消息时抛出异常,可以捕获异常,并设置Basic.Reject
来使用重试机制。


五 原理


1 rabbitmq的call原理是什么?
其中 RPC.CALL 基于请求与响应方式,RPC.CAST 只是提供单向请求
rpc call原理:
客户端创建 Message 时指定 reply_to 队列名、correlation_id 标记调用者。
通过队列,服务端收到消息。调用函数处理,然后返回。
返回的队列是 reply_to 指定的队列,并携带 correlation_id。
返回消息到达客户端,客户端根据 correlation_id 判断是哪一个函数的调用返回。

2 rpc cast原理是什么?
RPC.CAST 的远程调用流程与 RPC.CALL 类似,只是缺少了系统消息响应流程。
一个 Topic 消息生产者发送系统请求消息到 Topic 交换器,Topic 交换器根据消息的 Routing Key 将消息转发至共享消息队列。
与共享消息队列相连的所有 Topic 消费者接收该系统请求消息,并把它传递给响应的服务端进行处理。


参考:
https://blog.csdn.net/qq_30764991/article/details/80573352
https://blog.csdn.net/jerryDzan/article/details/89183625
https://msd.misuland.com/pd/3148108429789235368
https://www.cnblogs.com/starcrm/p/10619449.html
https://www.cnblogs.com/yulibostu/articles/10395545.html
https://cloud.tencent.com/developer/article/1453480
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值