MQ消息队列
一、什么是消息队列
MQ(Message Queue)消息队列,是一种跨进程的通信机制,用于上下游传递信息;作为一个队列,其主要的功能就是排队积压。面对高并发任务时,由于来不及同步处理,请求往往会发生堵塞,表现最为明显的就是对数据库的操作,如大量的insert、update之类的请求同时到达数据库,直接导致无数的行锁表锁,甚至最后请求会堆积过多,从而触发too many connections错误。
此外,当上游服务处理能力远大于下游的情况时,若上游服务直接调用下游服务,由于下游服务处理能力远跟不上上游服务,因此明显的后果就是下游服务因处理压力而导致崩溃.
因此,MQ提出之初就是为了削峰限流,通过异步处理请求,减少请求相应时间和逻辑及物理上的解耦,从而缓解系统的压力,轻松应对高并发的情况。
二、MQ在互联网中的应用举例
用户注册信息时,服务端收到用户的注册请求后,它会做这些操作:
【1】校验用户名等信息,如果没问题会在数据库中添加一个用户记录;
【2】如果是用邮箱注册会给你发送一封注册成功的邮件,手机注册则会发送一条短信;
【3】分析用户的个人信息,做消息或应用推送;
【4】发送给用户一个包含操作指南的系统通知等等……
但是对于用户来说,注册功能实际只需要第一步,只要服务端将他的账户信息存到数据库中他便可以登录上去做他想做的事情了。至于其他的事情,服务端可以把其他的操作放入对应的消息队列中然后马上返回用户结果,由消息队列异步的进行这些操作。
三、MQ背后工作模式
p2p(point to point)和Publish/Subscribe(Pub/Sub)
P2P模式包含三个角色:消息队列(Queue),发送者(Sender),接收者(Receiver)。每个消息都被发送到一个特定的队列,接收者从队列中获取消息。队列保留着消息,直到他们被消费或超时。
P2P的特点
【1】每个消息只有一个消费者(Consumer)(即一旦被消费,消息就不再在消息队列中);
【2】发送者和接收者之间在时间上没有依赖性,也就是说当发送者发送了消息之后,不管接收者有没有正在运行,它不会影响到消息被发送到队列;
【3】接收者在成功接收消息之后需向队列应答成功 。
如果希望发送的每个消息都会被成功处理的话,那么需要P2P模式。
该模式包含三个角色,主题(Topic),发布者(Publisher),订阅者(Subscriber)。 多个发布者将消息发送Topic,系统将这些消息传递给多个订阅者。
Pub/Sub的特点
【1】每个消息可以有多个消费者;
【2】发布者和订阅者之间有时间上的依赖性。针对某个主题(Topic)的订阅者,它必须创建一个订阅者之后,才能消费发布者的消息;
【3】为了消费消息,订阅者必须保持运行的状态
为了缓和这样严格的时间相关性,JMS允许订阅者创建一个可持久化的订阅。这样,即使订阅者没有被激活(运行),它也能接收到发布者的消息。
如果希望发送的消息可以不被做任何处理、或者只被一个消费者处理、或者可以被多个消费者处理的话,那么可以采用Pub/Sub模型。
四、MQ使用场景
【1】异步处理
【2】系统解耦
【3】流量削峰
【4】消息通讯
五、使用MQ的不足
【1】多了MQ中间件、系统成本增加,结构更复杂;
【2】消息传递路径更长,延时会增加;
【3】消息可靠性和重复性难以平衡,即不能同时保证消息不丢和不重复;
【4】发布方不知道接收方的执行结果。
【注意事项】:MQ不是任何场景都能使用的,当调用方实时依赖被调用方的执行结果时,不能使用MQ,应该同步调用。
六、常见的消息队列
【1】ActiveMQ
【2】RabbitMQ
【3】ZeroMQ
【4】Kafka(日志处理)
【5】MetaMQ
【6】RocketMQ