Redis打造低配版消息队列

Redis真的不愧是万金油,小到静态缓存,大到锁机制,消息队列,啥都能做。今天小马就来一起体验下redis实现消息队列的刺激感。

什么是消息队列

一听到消息队列,第一时间反应的当然是异步(请求链路长响应慢,则分开,并且有些动作可化同步为异步返回 ),限流,削峰(比如大量秒杀请求过来,先入队,后端自行按自己的节奏消费处理),解耦(比如上游订单服务处理完入队,下游有需要的自行订阅这个队列去处理)。本来想搞得正式一点的,查了下百科,一堆说明看得头晕,而且并不是很直观易懂。还是沿用一贯喜欢的招式,通俗一点讲吧。“消息队列”是在消息的传输过程中保存消息的容器。这句话真的非常精辟,可谓高度概括了这个词语的精髓。也就是说它其实是一个容器,至于容器是队列还是啥类型,它是不管的,能装就行。于是,我们来围观一下消息队列的两种模式或者说是消息通信模式:点对点模式和发布订阅模式。

点对点模式有的时候我们也叫做生产者消费者模式。生产者发送一条消息到queue,只有一个消费者能收到。也就是我们所说的1对1模式。

发布订阅模式我们有的时候也叫做广播。因为发布者发送到topic(主题有时也叫做频道channel,不同MQ取名不一样而已)的消息,只有订阅了topic的订阅者才会收到消息。也就是我们所说的1对多模式。

Redis实现原理

redis是如何实现上面两种模式的呢?还记得redis有一个数据类型叫List吗,我们通常直接称它为队列。因为它就是满足数据结构中队列的实现。于是,我们就用它来当容器实现消息队列。

实现点对点模式

我们在生产者客户端使用LPUSH命令将值依次插入某个KEY的列表当中,在消费者客户端使用LPOP命令移出并获取列表的第一个元素。这样就实现了一个简单的消息队列(请参照上面的说明图)。有人要问了,那我消费者如果去触发消费呢?嗯,是个好问题。简单的我们可以在消费者客户端直接使用while (true){consumerMessage();}这样子来轮询消费就可以了。

细心的你看肯定发现了,那这不是死循环吗?消费者不停地调用LPOP去查看List中是否有待处理消息,而这每一次都会发现一次连接,造成不必要的资源浪费。小机灵鬼的同学灵机一动,我可以采用休眠获取或者使用定时器隔段时间去获取呢。没错,这的确是个不错的方法,但是这个是存在问题的。

1.如果生产者速度大于消费者消费速度,消息队列长度会一直增大,时间久了会占用大量内存空间;

2.如果间隔时间过长,这样不能处理一些时效性的消息,睡眠时间过短,同样会在连接上造成比较大的资源开销。

那么有没有办法在生产者有数据的时候,我消费者就立马消费,如果没有数据则消费者一直等待,等到有数据了再立马消费呢?答应自然是肯定的。

我们来看Redis的阻塞获取列表系列的命令。先来看BLPOP命令,该命令移出并获取列表的第一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。命令格式如:BLPOP key1 [key2 ] timeout 。啥意思呢,就是现在我要获取一个或多个队列中的一个数据出来,如果没有我就一直阻塞,直到超时就返回nil。

所以,我们消费者使用BLPOP命令就可以在LIST没有数据的时候直接阻塞,大大减少不断连接的开销。有的同学说,我还是不过瘾,这里非要设置一个超时时间,因为不设置就会报错,但是我阻塞超时完如果LIST还是没有数据我还是得连接。别急,你把阻塞时间设置为0试试,是不是就是一直阻塞啦。于是就算“死循环”也不会怕了。

下面我们就用例子来大概体验一下吧。

生产者
消费者

我们注意到消费者客户端BLPOP runoobkey 0这个命令,获取test3值之前是在一直等待生产者加入数据,当生产者一旦写入数据,立马就获取到值,下面显示了等待时间是262.35s。

实现发布订阅模式

点对点模式讲完了,来聊聊发布订阅模式。教程如是说:Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。Redis 客户端可以订阅任意数量的频道。注意这里的频道概念,有些MQ也称为主题,但意思差不多。

可以理解为,驾驶人员(客户端)先都订阅了交通广播电台(频道),然后其中有一个客户端(电台DJ)向频道发送了一个消息(发布交通管制信息),所有驾驶人员都收听到了这条消息。哈哈,是不是很好理解。

那Redis的命令是怎么实现的呢?教程里的这块例子非常清晰了,笔者就直接借用了。

啊,大功告成。你认为这样就完了吗?不,还是太年轻了。

Redis消息队列有什么弊端

相比于市场上的主流MQ,Redis消息队列似乎被用得比较少,其实是有原因的,我们还是用通俗的语言聊一下缺陷。

点对点模式:

1.做消费确认ACK比较麻烦,就是不能保证消费者在读取之后,未处理后的宕机问题。导致消息意外丢失。通常需要自己维护一个Pending列表,保证消息的处理确认。也就是取出之后没有应答处理完毕了没,就当作消费成功了。没有可靠性。

2.不能重复消费,一旦消费就会被删除。这一点仁者见仁吧。

3.不支持分组消费,需要自己在业务逻辑层解决。

发布订阅模式:

1.消息一旦发布,不接收消息就没了。换句话就是发布时若客户端不在线,则消息丢失,不能寻回。也就是发布出去就不管对方有没接收到了,因为没有接收应答。

2.不能保证每个消费者接收的时间是一致的。这点仁者见仁吧。

3.若消费者客户端出现消息积压,到一定程度,会被强制断开,导致消息意外丢失。通常发生在消息的生产远大于消费速度时。似乎这个缺陷比较严重,可靠性大打折扣。

所以对可靠性要求不高的话可以考虑Redis简单搞搞,但一般现在都上主流MQ了,毕竟能用上MQ的项目,体量和项目可靠性要求一般也不会低。元芳,你怎么看?

参阅资料:

教程

资料1

资料2

拓展

拓展:ack机制

原创文章,未经允许请勿转载。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,186评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,858评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,620评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,888评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,009评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,149评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,204评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,956评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,385评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,698评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,863评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,544评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,185评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,899评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,141评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,684评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,750评论 2 351