1 、 exchange queue binding-key routing-key概念及相互间的关系
1.queue :存储消息的队列,能够指定name来惟一肯定
2.exchange:交换机(经常使用有三种),用于接收生产者发来的消息,并经过binding-key 与 routing-key 的匹配关系来决定将消息分发到指定queue
Direct(路由模式):彻底匹配 > 当消息的routing-key 与 exchange和queue间的binding-key彻底匹配时,将消息分发到该queue
Fanout (订阅模式):与binding-key和routing-key无关,将接受到的消息分发给有绑定关系的全部队列(不论binding-key和routing-key是什么)
Topic (通配符模式):用消息的routing-key 与 exchange和queue间的binding-key 进行模式匹配,当知足规则时,分发到知足规则的全部队列
2.为何要使用rabbitmq数据库
采用AMQP高级消息队列协议的一种消息队列技术,
实现了服务之间的高度解耦
1.在分布式系统下具有异步,削峰,负载均衡等一系列高级功能;
2.拥有持久化的机制,进程消息,队列中的信息也能够保存下来。
3.实现消费者和生产者之间的解耦。
4.对于高并发场景下,削峰限流,利于数据库的操做。
5.可使用消息队列达到异步下单的效果,排队中,后台进行逻辑下单。
3.使用rabbitmq的场景安全
1.服务间异步通讯
2.顺序消费
3.定时任务
4.请求削峰
4.如何确保消息正确地发送至RabbitMQ? 如何确保消息接收方消费了消息?如何避免消息重复投递或重复消费?服务器
持久化有两种方式 MQ事物(太耗性能,不使用)与confirm模式。
发送方确认模式:
将信道设置成confirm模式(发送方确认模式),则全部在信道上发布的消息都会被指派一个惟一的ID。
一旦消息被投递到目的队列后,或者消息被写入磁盘后(可持久化的消息),信道会发送一个确认给生产者(包含消息惟一ID)。
若是RabbitMQ发生内部错误从而致使消息丢失,会发送一条nack(not acknowledged,未确认)消息。
发送方确认模式是异步的,生产者应用程序在等待确认的同时,能够继续发送消息。当确认消息到达生产者应用程序,生产者应用程序的回调方法就会被触发来处理确认消息。
接收方确认机制
接收方消息确认机制:消费者接收每一条消息后都必须进行确认(消息接收和消息确认是两个不一样操做)。只有消费者确认了消息,RabbitMQ才能安全地把消息从队列中删除。
这里并无用到超时机制,RabbitMQ仅经过Consumer的链接中断来确认是否须要从新发送消息。也就是说,只要链接不中断,RabbitMQ给了Consumer足够长的时间来处理消息。保证数据的最终一致性;
下面罗列几种特殊状况:
若是消费者接收到消息,在确认以前断开了链接或取消订阅,RabbitMQ会认为消息没有被分发,而后从新分发给下一个订阅的消费者。(可能存在消息重复消费的隐患,须要去重)
若是消费者接收到消息却没有确认消息,链接也未断开,则RabbitMQ认为该消费者繁忙,将不会给该消费者分发更多的消息。
在消息生产时,MQ内部针对每条生产者发送的消息生成一个inner-msg-id,做为去重的依据(消息投递失败并重传),避免重复的消息进入队列;
在消息消费时,要求消息体中必需要有一个bizId(对于同一业务全局惟一,如支付ID、订单ID、帖子ID等)做为去重的依据,避免同一条消息被重复消费。
消息持久化,固然前提是队列、交换机必须持久化
RabbitMQ确保持久性消息能从服务器重启中恢复的方式是,将它们写入磁盘上的一个持久化日志文件,当发布一条持久性消息到持久交换器上时,Rabbit会在消息提交到日志文件后才发送响应。
一旦消费者从持久队列中消费了一条持久化消息,RabbitMQ会在持久化日志中把这条消息标记为等待垃圾收集。若是持久化消息在被消费以前RabbitMQ重启,那么Rabbit会自动重建交换器和队列(以及绑定),并从新发布持久化日志文件中的消息到合适的队列。
消息持久化
ACK确认机制
设置集群镜像模式
消息补偿机制
5.消息基于什么传输?网络
因为TCP链接的建立和销毁开销较大,且并发数受系统资源限制,会形成性能瓶颈。RabbitMQ使用信道的方式来传输数据。信道是创建在真实的TCP链接内的虚拟链接,且每条TCP链接上的信道数量没有限制。
6.消息如何分发?
若该队列至少有一个消费者订阅,消息将以循环(round-robin)的方式发送给消费者。每条消息只会分发给一个订阅的消费者(前提是消费者可以正常处理消息并进行确认)。
经过路由可实现多消费的功能
7.消息怎么路由?架构
消息提供方->路由->一至多个队列
消息发布到交换器时,消息将拥有一个路由键(routing key),在消息建立时设定。
经过队列路由键,能够把队列绑定到交换器上。
消息到达交换器后,RabbitMQ会将消息的路由键与队列的路由键进行匹配(针对不一样的交换器有不一样的路由规则);
经常使用的交换器主要分为一下三种:
fanout:若是交换器收到消息,将会广播到全部绑定的队列上
direct:若是路由键彻底匹配,消息就被投递到相应的队列
topic:可使来自不一样源头的消息可以到达同一个队列。 使用topic交换器时,可使用通配符
8.使用RabbitMQ有什么好处?并发
服务间高度解耦,
异步通讯性能高,
流量削峰
缺点:增长了系统复杂度,系统可用性低,外部依赖过多,一致性问题。
持久化的缺地就是下降了服务器的吞吐量,由于使用的是磁盘而非内存存储,从而下降了吞吐量。可尽可能使用 ssd 硬盘来缓解吞吐量的问题。
9.rabbitmq的集群负载均衡
主备模式:
普通集群模式:节点数据不复制,消息在某一台中,节点间通讯,一台挂了 就不可用了。
镜像集群模式:
你建立的queue,不管元数据仍是queue里的消息都会存在于多个实例上,而后每次你写消息到queue的时候,都会自动把消息到多个实例的queue里进行消息同步。
好处在于,你任何一个机器宕机了,没事儿,别的机器均可以用。坏处在于,第一,这个性能开销也太大了吧,消息同步全部机器,致使网络带宽压力和消耗很重!第二,这么玩儿,就没有扩展性可言了,若是某个queue负载很重,你加机器,新增的机器也包含了这个queue的全部数据,并无办法线性扩展你的queue
十、Kafka的高可用
Kafka 一个最基本的架构认识:由多个 broker 组成,每一个 broker 是一个节点;你建立一个 topic,这个 topic 能够划分为多个 partition,每一个 partition 能够存在于不一样的 broker 上,每一个 partition 就放一部分数据。异步
这就是自然的分布式消息队列,就是说一个 topic 的数据,是分散放在多个机器上的,每一个机器就放一部分数据。分布式
写数据的时候,生产者就写 leader,而后 leader 将数据落地写本地磁盘,接着其余 follower 本身主动从 leader 来 pull 数据。一旦全部 follower 同步好数据了,就会发送 ack 给 leader,leader 收到全部 follower 的 ack 以后,就会返回写成功的消息给生产者。(固然,这只是其中一种模式,还能够适当调整这个行为)高并发
消费的时候,只会从 leader 去读,可是只有当一个消息已经被全部 follower 都同步成功返回 ack 的时候,这个消息才会被消费者读到。
十一、什么状况下会出现 blackholed 问题?
答:blackholed 问题是指,向 exchange 投递了 message ,而因为各类缘由致使该 message 丢失,但发送者殊不知道。可致使 blackholed 的状况:1.向未绑定 queue 的 exchange 发送 message;2.exchange 以 binding_key key_A绑定了 queue queue_A,但向该 exchange 发送 message 使用的 routing_key 倒是 key_B。
十二、如何防止出现 blackholed 问题?
答:没有特别好的办法,只能在具体实践中经过各类方式保证相关 fabric 的存在。另外,若是在执行 Basic.Publish 时设置 mandatory=true ,则在遇到可能出现 blackholed 状况时,服务器会经过返回 Basic.Return 告之当前 message 没法被正确投递(内含缘由 312 NO_ROUTE)。
1三、Consumer Cancellation Notification 机制用于什么场景?
答:用于保证当镜像 queue 中 master 挂掉时,链接到 slave 上的 consumer 能够收到自身 consume 被取消的通知,进而能够从新执行 consume 动做重新选出的 master 出得到消息。若不采用该机制,链接到 slave 上的 consumer 将不会感知 master 挂掉这个事情,致使后续没法再收到新 master 广播出来的 message 。另外,由于在镜像 queue 模式下,存在将 message 进行 requeue 的可能,因此实现 consumer 的逻辑时须要可以正确处理出现重复 message 的状况。
1四、Basic.Reject 的用法是什么?
答:该信令可用于 consumer 对收到的 message 进行 reject 。若在该信令中设置 requeue=true,则当 RabbitMQ server 收到该拒绝信令后,会将该 message 从新发送到下一个处于 consume 状态的 consumer 处(理论上仍可能将该消息发送给当前 consumer)。若设置 requeue=false ,则 RabbitMQ server 在收到拒绝信令后,将直接将该 message 从 queue 中移除。
另一种移除 queue 中 message 的小技巧是,consumer 回复 Basic.Ack 但不对获取到的 message 作任何处理。
而 Basic.Nack 是对 Basic.Reject 的扩展,以支持一次拒绝多条 message 的能力。
1五、什么是死信呢?什么样的消息会变成死信呢?
方便咱们查看消息失败的缘由了
消息被拒绝(basic.reject或basic.nack)而且requeue=false.
消息TTL过时
队列达到最大长度(队列满了,没法再添加数据到mq中)
1六、若是让你写一个消息队列,该如何进行架构设计?说一下你的思路。
快速扩容, 分布式, 数据持久化, 磁盘顺序读写, 高可用, 消息0丢失(ack)
1七、rabbitMQ怎么作的持久化
写入文件前会有一个Buffer,大小为1M(1048576),数据在写入文件时,首先会写入到这个Buffer,若是Buffer已满,则会将Buffer写入到文件(未必刷到磁盘)
有个固定的刷盘时间:25ms,也就是无论Buffer满不满,每隔25ms,Buffer里的数据及未刷新到磁盘的文件内容一定会刷到磁盘
每次消息写入后,若是没有后续写入请求,则会直接将已写入的消息刷到磁盘:使用Erlang的receive x after 0来实现,只要进程的信箱里没有消息,则产生一个timeout消息,而timeout会触发刷盘操做
1八、RabbitMQ、kafka之间的比较
一、 RabbitMq比kafka成熟,在可用性上,稳定性上,可靠性上,RabbitMq超过kafka。rabbitMq 延迟度低。
二、 Kafka设计的初衷就是处理日志的,能够看作是一个日志系统,针对性很强,因此它并无具有一个成熟MQ应该具有的特性(不支持事物)
三、 Kafka的性能(吞吐量、tps)比RabbitMq要强,这篇文章的做者认为,二者在这方面没有可比性。
4.技术上面,使用rabbitMq比kafka 长,二者社区活跃度都高。
5.RocketMQ 阿里出品,社区活跃度不是很高,技术实力强大的公司可选择。