消息队列
消息队列
一,消息队列内部实现原理
尚硅谷客户端A给客户端B发送数据时,有两种情况,如果客户端B出现问题就发送不过去了,如果发送为10M/S,接收为5M/S的话有可能丢数据。消息队列就是A发送数据不直接发送给B, 先发送给消息队列,B接收消息有两种模式。
1. 点对点模式(一对一,消费者主动拉取数据,消息收到后消息清除)
点对点模式通常是一个基于拉取或者轮询的消息传送模型,这种模型从队列中请求消息,而不是将消息推送到客户端。这个模型的特点是发送到队列的消息被一个且只有一个接收者接收处理,即使有多个消息监听者也是如此。实时有线程去监控,有数据才能获取。
2. 发布/订阅模式(一对多,数据生产后,推送给所有订阅者)
发布订阅模型则是一个基于推送的消息传送模型。发布订阅模式可以有多种不同的订阅者,临时订阅者只在主动监听主题时才接收消息,而持久订阅者则监听主题的所有消息,即使当前订阅者不可用,处于离线状态。
二,为什么需要消息队列?
1. 使用同步的方式来解决多个服务之间的通信,会导致性能和稳定性的问题
千锋教育(1). 下单的每个步骤 -- 创建订单,减库存,改积分,发优惠卷,创建成功。这些步骤都需要花费相应的响应时间,用户就会发觉下单的体验很差。
(2). 一旦网络不稳定,就可能会出现某个环节突然失败,下单不成功,重新下单的情况,用户体验差。
2. 使用异步的通信方式
针对于同步的通信方式来说,异步的方式,可以让上游快速成功,极大提高了系统的吞吐量,而且在分布式系统中,通过下游多个服务器的分布式事务的保障,也能保证业务执行之后最终一致性。
千锋教育下订单时,上游服务器只需要花500ms的时间把一条消息发送给消息队列,然后进入订单创建成功的状态。每个服务,即订阅者,从消息队列中获得具体的业务信息,再顺序进行,如果某个环节失败了,可以通过分布式事务解决方案来保证最终成功。
总结:使用异步通信,就要用到消息队列
消息队列解决具体的是什么问题 -- 通信问题
三,什么是MQ
Message Queue (MQ), 消息队列中间件。很多人都说:MQ通过将消息的发送和接收分离开,来实现应用程序的异步和解耦,这个给人的直觉是 -- MQ是异步的,用来解耦的。但是这个只是MQ的效果,不是目的。MQ真正的目的是为了通讯,屏蔽底层复杂的通讯协议,定义了一套应用层的,更加简单的通讯协议。HTTP协议很难实现两端通讯 -- 模块A可以调用模块B,模块B也可以调用模块A,如果要做到这个,两端都要背上WebServer,而且还不支持长连接。TCP更加原始,粘包、心跳、私有的协议,想一想头皮就发麻。MQ所要做的就是在这些协议上构建一个简单的“协议” -- 生产者/消费者模型。MQ带给我的“协议”不是具体的通讯协议,而是更高层次的通讯模型。它定义了两个对象 -- 发送数据的叫生产者;接收数据的叫消费者,提供一个SDK,让我们可以定义自己的生产者和消费者,实现消息通讯而无视底层通讯协议。
四,消息队列的流派
目前消息队列的中间件选型有很多种:
rabbitMQ: 使用简单,功能性强
rocketMQ: 阿里内部,根据kafka的内部执行原理,手写的一个消息队列中间件,性能与kafka相比肩,除此之外,在功能上封装了更多的功能
Kafka: 全球消息处理性能最快的一款MQ
zeroMQ
五,这些消息队列中间件有什么区别?
1. 有Broker的MQ
这个流派通常有一台服务器作为Broker,所有的消息通过它中转。生产者把消息发送给它就结束自己的任务了,Broker则把消息主动推送给消费者(或者消费者主动轮询)
(1). 重Topic: Kafka, RocketMQ, ActiveMQ
整个broker,依据topic来进行消息的中转。在重topic的消息队列里必然需要topic的存在。
Kafka, JMS(ActiveMQ)就属于这个流派,生产者会发送key和数据到Broker,由Broker比较key之后决定给哪个消费者。这种模式是我们最常见的模式,是我们对MQ最多的印象。在这种模式下,一个Topic往往是比较大的概念,甚至一个系统中就可能只有一个topic, topic某种意义上就是queue,生产者发送key相当于说"hi, 把数据放到key的队伍中"。
千锋教育(2). 轻Topic: RabbitMQ
topic只是一种中转模式。
内部可以用Topic,也可以不用。这种的代表是RabbitMQ(或者说是AMQP)。生产者发送key和数据,消费者定义定义订阅的队列,Broker收到数据之后会通过一定的逻辑计算出key对应的队列,然后把数据交给队列。
千锋教育2. 无Broker
生产者和消费者之间没有使用Broker,例如ZeroMQ,直接使用socket进行通信。
无Broker的MQ的代表是ZeroMQ。该作者非常睿智,他非常敏锐的意识到 -- MQ是更高级的Socket, 它是解决通讯问题的。所以ZeroMQ被设计成了一个“库”,而不是一个中间件。这种实现也可以达到 -- 没有Broker的目的。
千锋教育节点之间通讯的消息都是发送到彼此的队伍中,每个节点都既是生产者,又是消费者。ZeroMQ做的事情就是,封装一套类似socket的API,可以完成发送数据,读取数据。
ZeroMQ其实就是一个跨语言的,重量级的Actor模型邮箱库。你可以把自己的程序想象成一个Actor,ZeroMQ就是提供邮箱功能的库;ZeroMQ可以实现同一台机器的RPC通讯也可以实现不同机器的TCP, UDP通讯,如果你需要一个强大的、灵活的、野蛮的通讯能力,别犹豫ZeroMQ.
五,消息队列的优点
1. 解耦
允许你独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束。
2. 冗余
消息队列把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据丢失风险。许多消息队列所采用的“插入-获取-删除”范式中,在把一个消息从队列中删除之前,需要你的处理系统明确的指出该消息已经被处理完毕,从而确保你的数据被安全的保存直到你使用完毕。
3. 扩展性
因为消息队列解耦了你的处理过程,所以增大消息入队和处理频率是很容易的,只要另外增加处理过程即可。
4. 灵活性 & 峰值处理能力
在访问量剧增的情况下,应用仍然需要继续发挥作用,但是这样的突发流量并不常见。如果为能处理这类峰值访问为标准来投入资源对视待命无疑是巨大的浪费。使用消息队列能够使关键组件顶住突发的访问压力,而不会因为突发的超负荷的请求而完全崩溃。
5. 可恢复性
系统的一部分组件失效时,不会影响到整个系统。消息队列降低了进程间的耦合度,所以即使一个处理消息的进程挂掉,加入队列中的消息仍然可以在系统恢复后被处理。
6. 顺序保证
在大多使用场景下,数据处理的顺序都很重要。大部分消息队列本来就是排序的,并且能保证数据会按照特定的顺序来处理。
7. 缓冲
有助于控制和优化数据流经过系统的速度,解决生产消息和消费消息的处理速度不一致的情况。
8. 异步通信
很多时候,用户不想也不需要立即处理消息。消息队列提供了异步处理机制,允许用户把一个消息放入队列,但并不立即处理它。想向队列中放入多少消息就放多少,然后在需要的时候再去处理。