消息队列
什么是消息中间件
消息中间件,是利用高效可靠的消息传递机制进行异步的数据传输,并基于数据通信进行分布式系统的集成。通过提供那个消息队列模型和消息传递机制,可以在分布式环境下扩展进程间的通信。
消息中间件的传递模式
1.点对点模式
消息生产者讲消息发送到队列种,消息消费者从队列中接收消息。消息可以在队列中进行异步传输。
2.发布/订阅模式
发布订阅模式是通过一个内容节点来发布和订阅消息,这个内容结点成为主题,消息发布者将消息发布到某个主题,消息订阅者订阅这个主题的消息,主题相当于一个中介。主题的消息的发布与订阅相互独立,该模式的消息的传播是一对多的模式。
消息中间件可以做什么
应用程序之间可以不采取直接通信,而是采取消息中间件作为中介,做到数据的异步通信。开发人员不需要考虑网络协议和远程调用的问题,只需要通过各种消息中间件提供的API,就可以完成简单的消息推送,和消息接收等业务功能。
消息的生产者将消息存储到队列中,消息的消费者不一定马上消费消息,可以的能到自己想要用到这个消息的时候,再从响应的队列中获取消息。这样的设计可以很好的解决大数据传输过程中占用资源的问题,使数据传递和平台分开,不需要分配资源用于数据传输,有效的利用当前的资源。
常见的消息队列
Message Quene(MQ)
在互联网中,多台设备产生通信的数据的总称:可以是视频、文本、音频等等。
一种特殊的线性表,满足先进先出的原则。
Kafka介绍
kafka是分布式的基于消息的发布-订阅的消息队列。LinkedIn(领英),Scala编写的
2.2 三大特点
可满足每秒百万级别的消息的生产和消费
具备一套完整的消息的存储机制,可以确保消息数据的高效的安全的持久化
既有扩展以及容错性。
2.3 kafka服务
- topic : 主题,kafka处理的消息分为不同的分类,分类就是按照主题来划分。
- broker:消息服务器的代理。kafka集群中的一个节点一般我都门都叫做一个broker;主要是用来存储消息。存在硬盘中。
- partition:分区。Topic的在物理上的分组。一个topic在broker上被分为1个或者多个partition。分区在创建主题的时候指定的。
- message:消息,通信的基本单位,每个消息属于某一个partition
- Producer: 生产者,消息和数据都是由这个组件产生的,由它发送到kafka集群中的。
- Consumer:消费者,消息和数据都是由这个组件来消费的。
- Zookeeper: 他需要zk来做分布式协调
Kafka架构
RabbitMQ消息队列
使用Erlang语言开发的开源消息队列系统,基于AMQP协议来实现
AMQP协议更多的用于企业系统中,对数据一致性、稳定性和可靠性要求很高的场景,对性能和吞吐量的要求还在其次。AMQP(高级消息队列协议)是一个进程间传递一部消息的网络协议。发布者发布消息,经过交换机,交换机根据路由规则将收到的消息分发给交换机绑定的队列,最后AMQP代理会将消息传递给此队列的消费者,或者消费者按照需求自动获取。
RocketMQ消息队列
RocketMQ是阿里开源的消息中间件,目前也已经孵化为Apache的顶级项目,它是纯Java开发,具有高吞吐量、高可用性、适合大闺蜜分布式系统的特点。
该消息队列的设计思路起源于Kafka,他对消息的可靠传输和事务的性能做了优化,目前被阿里集团广泛应用于交易、充值、流计算、消息推送、日志流处理、binglog分发等场景。
ActiveMQ消息队列
Apache的开源产品,完全支持JMS规范的消息中间件,是一个纯Java的程序,因此只需要操作系统支持Java虚拟机的,ActiveMQ即可执行。
JMS即为Java Message Service的应用程序接口,是一个Java平台中关于面向消息中间件的API,用于在两个程序之间,或分布式系统中发送消息,进行异步通信。
1.Distination目的地,消息发送者需要指定Destination才能发送消息,接收者需要指定Destination才能接收消息
2.Producer是生产者,生产数据,Consumer是消费者,接收数据
3.Message是消息封装一次后通信的内容
zeroMQ
正确的说,zeroMQ不是TCP,不是socket,也不是消息队列,而是这些的综合体
zeroMQ又称Ø MQ
Ø 也是一个非常奇妙的符号:
1.Ø 是一种权衡
2.Ø 暗合“零代理”、“零延迟”
3.Ø 的目标是“零管理、零消耗、零浪费”
4.Ø 符合简约注意,以减低复杂度作为力量的源泉,而不是增加新的功能
zeroMQ与消息队列相比的特点:
1.点对点无中间节点
致力于把点对点模式做到极致
2.强调消息收发机制
对通信的模式做了总结
例如数据的推送,接收 等
- PUB and SUB
- REQ and REP
- REQ and XREP
- XREQ and REP
- XREQ and XREP
- XREQ and XREQ
- XREP and XREP
- PUSH and PULL
- PAIR and PAIR
3.以统一接口支持多种底层通信方式
不管是线程间通信,进程间通信还是跨主机通信,zeroMQ都使用同一套API进行调用,在调用的时候只需要修改对应的协议名称即可
Redis实现消息队列
Redis实现轻量级的消息队列与消息中间件,没有高级特性也没有ACK保证,无法做到数据不重不漏,如果业务简单而且对消息的可靠性要求不严格的可以试用。
Redis存储类型:
Redis中列表List类型是按照插入顺序的字符串链表,和数据结构中的普遍链表一样,可以在头部left和尾部right添加新的元素。插入时如何键不存在Redis将为该键创建一个新的链表。如果链表中所有元素均被删除,那么该键也被删除。
Redis的列表List可以包含的最大元素数量为4294967295,从元素插入和删除的效率来看,如果是在链表的两头插入或删除元素将是非常高效的操作。即使链表中已经存储了数百万条记录,该操作也能在常量时间内完成。然后需要说明的是,如果元素插入或删除操作是作用于链表中间,那将是非常低效的。
Redis中对列表List的操作命令中,L表示从左侧头部开始插入和弹出,R表示从右侧尾部开始插入和弹出。
Redis提供了两种方式来做消息队列,一种是生产消费模式,另一种是发布订阅模式。
生产消费模式
生产消费模式会让一个或多个客户端监听消息队列,一旦消息到达,消费者马上消费,谁先抢到算谁的。如果队列中没有消息,消费者会继续监听。
PUSH/POP
Redis数据结构的列表List提供了push和pup命令,遵循着先入先出FIFO的原则。使用push/pop方式的优点在于消息可以持久化,缺点是一条消息只能被一个消费者接收,消费者完全靠手速来获取,是一种比较简陋的消息队列。
Redis的队列list是有序的且可以重复的,作为消息队列使用时可使用rpush/lpush操作入队,使用lpop/rpop操作出队。当发布消息是执行lpush命令,将消息从列表左侧加入队列。消息接收方执行rpop命令从列表右侧弹出消息。
如果队列空了怎么办呢?
如果队列空了,消费者会陷入pop死循环,即使没有数据也不会停止。空轮询不但消耗消费者的CPU资源还会影响Redis的性能。傻瓜式的做法是让消费者的线程按照一定的时间间隔不停的循环和监控队列,虽然可行但显然会造成不必要的资源浪费,而且循环周期也很难确定。
对于消费者而言存在一个问题,需要不停的调用rpop查看列表中是否有待处理的消息。每调用一次都会发起一次连接,势必造成不必要的资源浪费。如果使用休眠的方式让消费者线程间隔一段时间再消费,但这样做也有两个问题:
如果生产者速度大于消费者消费的速度,消息队列长度会一直增大,时间久了会占用大量内存空间。
如果休眠时间过长,就无法处理一些时效性的消息。如果休眠时间过短也会在连接上造成比较大的开销。
当LPOP返回一个元素给客户端时会从List中将该元素移除,这意味着该元素只存在于客户端的上下文中。如果客户端在处理这个返回元素的过程中崩溃了,这个元素就会永远的丢失掉。
pulsar消息队列
待补充