9.1 Redis消息队列实战

在实际项目中,模块间可以通过消息队列(Message Queue,MQ)来交互数据,比如订单模块在处理好一个订单后可以把该订单对象放入消息队列,而记账模块则可以从该消息中取出订单对象继续执行

9.1.1 消息队列与Redis消息订阅发布模式

如下图示,订单模块和记账模块通过MQ交互数据.在MQ中,以FIFO的方式存储订单对象.即:订单模块在队列头部插入订单,记账模块从队列头部获取订单并处理

消息队列效果图

用MQ来交互数据的好处是"解耦".在刚才的例子中,订单模块和记账模块间在交互数据时无需考虑对方的业务细节.在实际项目中,一般会用到一些成熟的MQ中间件,例如Kafka和RabbitMQ等,而通过Redis的消息订阅和发布模式也能实现MQ的效果

Redis的消息订阅和发布模式是一种消息的通信模式,其中发布者(publisher)可以向指定的频道(channel)发送消息,消息发送后订阅该频道的订阅者(subscriber)能收到消息.如下图示:

Redis消息订阅发布模式效果图

其中,每个channel中都包含1个消息队列,当publisher向特定的channel发送多个消息后,这些消息会以队列的形式存储,并被订阅该channel的subscriber处理

这样一来,publisher在发送消息后无需关注有多少个subscriber,也无需关注subscriber处理消息的细节.反之亦然.subscriber也无需关注publisher的细节.也就是说,通过这套消息订阅和发布模式,可以最大限度地解耦模块间的交互动作

9.1.2 消息订阅发布的命令和流程

Redis通信模块效果图

如上图示,存储消息的channel在redisPublisher实例中.当连接redisPublisher实例的客户端创建MQChannel后,连接redisSub1和redisSub2实例的客户端会订阅该channel,这样当channel中有消息时,2个客户端能够自动接收消息

  • step1. 创建redisPublisher实例并创建channel

编写配置文件:

启动服务:

使用客户端连接该实例,并发布消息:

  • PUBLISH channel message

    • 功能: 向指定的频道发送消息.若指定的频道不存在,则会创建一个.返回值表示接收到信息的订阅者数量

    • channel:频道名

    • message:待发送的消息

  • step2. 创建redisSub1客户端,并订阅频道

  • SUBSCRIBE channel [channel ...]

    • 功能:订阅给定的一个或多个频道的信息

    • channel:给定的channel名

  • step3. 在连接redisPublisher的客户端中发布消息

  • step4. 观察redisSub1客户端的订阅结果

可以看到,客户端成功订阅了myChannel频道的消息.因此其他客户端向该channel发送消息,则该客户端立刻就能收到

  • step5. 创建redisSub2客户端,并订阅频道

  • step6. 在step1的客户端中发布2条消息

  • step7. 观察redisSub1客户端

  • step8. 观察redisSub2客户端

9.1.3 消息订阅发布的相关命令汇总

  • PSUBSCRIBE pattern [pattern ...]

    • 功能:订阅一个或多个符合给定模式的频道

  • UNSUBSCRIBE channel [channel ...]

    • 退订给定的一个或多个频道

9.1.4 GO与消息队列的实战范例

由于Pub/Sub并不是常用功能,故本例将使用比较简单的项目结构来演示

发布者端

订阅者端

运行

  • step1. 运行订阅者

此时由于发布者尚未发送消息,故订阅者hang在了死循环中

  • step2. 运行发布者

  • step3. 观察订阅者

可以看到,订阅者在收到消息后,可以完成跳出死循环的功能

Last updated