当前位置:首页 > 问答 > 正文

用Redis消息组件轻松搞定信息收发,快速上手没烦恼

说到让程序之间能够互相传递信息,也就是我们常说的信息收发,听起来好像是个挺复杂的技术活儿,一想到要搭建消息队列,什么RabbitMQ、Kafka这些名字就冒出来了,感觉门槛一下子就高了,但你知道吗?其实我们手边一个非常常用的工具——Redis,就能轻松搞定很多场景下的信息收发需求,而且上手特别快,根本没那么多烦恼。

(来源:基于Redis官方文档对Pub/Sub模式和List结构的介绍)

Redis本身是一个内存数据库,以速度快而闻名,它除了能存数据,还提供了两种特别实用的功能来实现信息传递,这两种功能就像是两条不同的路,适合不同的情况。

第一条路:像广播一样喊话——发布订阅模式

这种模式特别像我们生活中的广播站或者微信群,想象一下,有一个聊天频道,有的人在这个频道里说话(发布消息),而其他在这个频道里的人都能同时听到(订阅消息),这就是发布订阅模式的核心。

具体怎么用呢?非常简单,需要接收信息的程序(我们叫它订阅者)先要“蹲守”在一个或多个特定的“频道”上,一个程序执行一条命令 SUBSCRIBE news_sports,意思就是:“我要订阅‘体育新闻’这个频道,这个频道一有消息就立刻告诉我。”

另一个负责发送信息的程序(发布者)就可以往这个频道里“喊话”了,它执行 PUBLISH news_sports "湖人队今天夺冠了!" 这条命令,Redis服务器一收到这个命令,就会立刻把“湖人队今天夺冠了!”这个消息,送给所有当时正在订阅 news_sports 这个频道的程序,这些订阅者就会几乎在同一时间收到这条消息并进行处理。

(来源:Redis命令参考中的PUBLISH和SUBSCRIBE命令)

这种方式的好处是速度快,而且是“一对多”的,一条消息可以同时被很多个程序收到,非常适合做实时通知、新闻推送、在线聊天室这类场景,网站上有一个“最新公告”栏,后台管理员发布一条新公告,所有打开网页的用户都能立刻看到更新,就是用这种模式实现的。

用Redis消息组件轻松搞定信息收发,快速上手没烦恼

但它也有个特点,瞬间即逝”,如果某个程序在发布者发布消息的那一刻没有在频道里蹲守(比如它当时网络断了,或者还没启动),那么它就永远错过了这条消息,这就像广播,你没打开收音机,就听不到当时广播的内容。

第二条路:像排队取快递——基于列表的队列

如果你担心消息丢失,或者希望消息能被有条不紊地一个一个处理,那么这第二条路就更合适了,它利用的是Redis里一个叫“列表”的数据结构,工作原理很像我们去银行排队取号。

发送信息的程序(生产者)执行 LPUSH my_task_queue "任务A" 命令,相当于把“任务A”这个纸条放进一个名叫 my_task_queue 的盒子(列表)的最左边(头部)。

接收信息的程序(消费者)则执行 RPOP my_task_queue 命令,相当于从同一个盒子的最右边(尾部)取出一张纸条来处理,这样,先放进去的任务(比如任务A)会最后被取出来,形成了一个“先进后出”的栈结构,如果你希望是“先进先出”的队列,也很简单,生产者用 LPUSH,消费者用 LPOP 就行了,或者反过来用 RPUSHRPOP

用Redis消息组件轻松搞定信息收发,快速上手没烦恼

(来源:Redis数据结构List相关的命令,如LPUSH, RPOP等)

这种方式最大的好处就是消息不会丢,只要Redis服务器不宕机,消息就会安安稳稳地待在列表里,等着消费者来取,即使消费者程序暂时下线了,重启之后它还可以继续从队列里取出积压的消息进行处理,这就非常适合处理一些不那么紧急但要求可靠的任务,比如发送邮件、处理图片、同步数据等后台作业。

举个例子,用户在你的网站上上传了一张头像,你的Web程序可以立刻响应“上传成功”,同时把“压缩用户123的头像图片”这个任务放进Redis队列,后台专门处理图片的程序会不停地从队列里取任务来处理,这样既保证了网站响应速度快,又确保了耗时的图片处理工作能完成。

怎么选?

你看,用Redis做消息收发是不是一下子就清晰了?

  • 如果你想做实时、广播式的通知,消息丢了也没太大关系,那就用发布订阅模式。
  • 如果你想做可靠、排队式的任务处理,确保每个消息都必须被处理,那就用列表队列模式。

很多时候,在一个项目里这两种方式还会结合使用,用户下单成功后,用列表队列通知发货系统准备商品(确保发货任务不丢失),同时用发布订阅模式向用户的浏览器推送一条实时通知:“亲,您的订单已支付成功!”

下次当你需要实现程序间的通信时,别急着去研究那些庞大复杂的专业消息系统,先想想Redis,它可能用几条简单的命令,就能轻松解决你的烦恼,让你快速上手,把精力更多地放在业务逻辑本身。