写在前面:Redis的消息队列并不是专业的消息队列,没有ACK保证,没有特别多的高级特性,如果对消息的可靠性有很高的要求,就放弃它吧。

1.Redis消息队列

Redis通过内部的list数据结构来实现异步消息队列。通过`rpush`和`lpop`操作结合构成类似队列(先进先出)的效果;也可以通过`rpush`与`rpop`构成堆栈(后进先出)的效果。但一般消息队列都采用队列效果的组合形式。

>rpush hobby basketball football tennis
(integer) 3
>lpop hobby
"basketball" >lpop hobby
"football" >lpop tennis
"tennis" >lpop hobby
(nil)

客户端通过队列的pop操作获取消息,然后进行处理,处理完了再接着获取消息,然后再处理,一直循环,这就是队列消费者客户端的生命周期。

如上所述,假如队列空了,pop操作拿不到数据,客户端因此陷入一直pop的死循环产生一堆无用的空轮询,同时消耗着客户端和Redis服务端的资源,怎么办?

首先能想到的方法可能会是让队列为空的请求,通过sleep命令让线程停下来。更好的做法是通过blpopbrpop代替之前的lpoprpop,即用阻塞读(在队列没有数据时,立即进入休眠状态;当数据到来,立刻重新请求)的方式,解决因为sleep命令带来的延迟。

但这样就会有新的问题产生:当列表长时间没有数据时,客户端线程会一直被阻塞,形成闲置连接,而这种情况下,服务器为了节省资源通常会断开这条链接。客户端的blpop/brpop就会报错。

所以编写客户端消费者时要捕获异常,进行重试。

2.延时队列

延时队列的出现是为了解决在分布式开发中,客户端在处理请求时加锁失败的问题。这种方式是将当前冲突的请求扔进另一个队列延后处理以避开锁的冲突。

在Redis中延时队列的实现是由zset(有序列表)来实现,基本使用方式为zset key score value。在延时队列中常常把消息序列化成一个字符串作为 zsetvalue,消息的过期时间作为score,然后用多个线程(保证可用性)来轮询zset来获取到期的任务进行处理。考虑到并发抢任务,任务就有可能被多次执行。

def delay(msg):
msg.id = str(uuid4()) #序列化保证value的唯一性
value = json.dumps(msg)
retry_ts = time.time() + 5 # 5s后重试
redis.zadd('delay-queue',retry_ts,value) def loop():
while True:
# 最多取一条
value_list = redis.zrangebyscore("delay-queue",0,time.time(),start=0,num=1):
if not value_list:
time.sleep(1)
continue
value = value_list[0]
# 将取到的消息从redis消息队列中删除
success = redis.zrem("delay-queue",value)
# 多进程并发下,只有一个线程可以抢到消息
if success:
msg = json.loads(value)
handle_msg(msg)

Redis中的`zrem`方法是保证多线程争抢任务不发生混乱的关键。
需要注意的是在执行*handle_msg()* 时一定要进行异常捕获,避免因单个任务出现问题导致循环异常退出。

Redis学习笔记02-消息队列与延时队列的更多相关文章

  1. Redis学习笔记~实现消息队列比MSMQ更方便

    什么是队列:简单的说就是数据存储到一个空间里(可以是内存,也可以是物理文件),先存储的数据对象,先被取出来,这与堆栈正好相反,消息队列也是这样,将可能出现高并发的数据进行队列存储,并按着入队的顺序依次 ...

  2. redis学习笔记-02:为什么使用NoSQL数据库

    一.第一代:单机版的MySQL 1.静态网页,动态交互类型的网站不多. 2.架构:APP---->DAL---->MySQL Instance 3.数据存储的瓶颈: (1)数据量总大小超过 ...

  3. redis学习笔记-02 list列表类型命令

    一.lpush key value1 value2 value3 value4(命令将一个或多个值插入到列表头部. 如果 key 不存在,一个空列表会被创建并执行 LPUSH 操作) lpush k1 ...

  4. Redis学习笔记~目录

    回到占占推荐博客索引 百度百科 redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合). ...

  5. Redis:学习笔记-02

    Redis:学习笔记-02 该部分内容,参考了 bilibili 上讲解 Redis 中,观看数最多的课程 Redis最新超详细版教程通俗易懂,来自 UP主 遇见狂神说 4. 事物 Redis 事务本 ...

  6. Linux进程间通信IPC学习笔记之消息队列(SVR4)

    Linux进程间通信IPC学习笔记之消息队列(SVR4)

  7. Redis学习笔记4-Redis配置详解

    在Redis中直接启动redis-server服务时, 采用的是默认的配置文件.采用redis-server   xxx.conf 这样的方式可以按照指定的配置文件来运行Redis服务.按照本Redi ...

  8. Redis学习笔记4-Redis配置具体解释

    在Redis中直接启动redis-server服务时, 採用的是默认的配置文件.採用redis-server   xxx.conf 这种方式能够依照指定的配置文件来执行Redis服务. 依照本Redi ...

  9. Redis学习笔记八:集群模式

    作者:Grey 原文地址:Redis学习笔记八:集群模式 前面提到的Redis学习笔记七:主从复制和哨兵只能解决Redis的单点压力大和单点故障问题,接下来要讲的Redis Cluster模式,主要是 ...

  10. redis学习笔记(详细)——高级篇

    redis学习笔记(详细)--初级篇 redis学习笔记(详细)--高级篇 redis配置文件介绍 linux环境下配置大于编程 redis 的配置文件位于 Redis 安装目录下,文件名为 redi ...

随机推荐

  1. hexo 错误汇总

    文章目录 发布文章遇到: 发布文章的时候出现错误: 代码推送到github,hexo g -d 半天推送不上去 记录一次hexo+coding hexo s本都没问题,hexo g -d 样式并未改变 ...

  2. Font Awesome 完全兼容 Bootstrap 的所有组件。

    "F_FullName": "其他", "F_Icon": "glyphicon glyphicon-backward fa-lg ...

  3. 安装MySQL出现的this application

    1,https://www.microsoft.com/zh-cn/download/confirmation.aspx?id=1385 2,安装Windows 图像组件 (WIC)以及NET Fra ...

  4. Java程序员必备的10个大数据框架!

    作者:java妞妞 blog.csdn.net/javaniuniu/article/details/71250316 当今IT开发人员面对的最大挑战就是复杂性,硬件越来越复杂,OS越来越复杂,编程语 ...

  5. ElasticJob-分布式作业调度神器,你们还在用Quartz吗?!

    简介 Elastic-Job是一个分布式调度解决方案,由两个相互独立的子项目Elastic-Job-Lite和Elastic-Job-Cloud组成. Elastic-Job-Lite定位为轻量级无中 ...

  6. java中一个类不想被继承怎么办?

    方法一:把类声明为final 方法二:对类中的构造器声明为private,类中提供一个static方法,完成对类的初始化.如下代码: public class Base{ private Base() ...

  7. windows系统下jupyter notebook使用虚拟环境

    目录 [亲测好使]windows系统下jupyter notebook使用虚拟环境 在虚拟环境中安装jupyter,并添加到jupyter kernel 参考 [未测试,但觉得比上面那方法好,因为上面 ...

  8. 滑雪 矩阵中的最长上升路径 /// 记忆化DFS || DP oj22919

    大致题意: Description 难怪Michael喜欢滑雪,因为滑雪确实很刺激.为了获得加速度,滑雪道必须向下倾斜,而且当滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道在一 ...

  9. 把类完善了一下,播放器也完善了一下,纯MFC与WinMM的产物

  10. 2019-5-15-影子系统让-C++-程序无法运行

    title author date CreateTime categories 影子系统让 C++ 程序无法运行 lindexi 2019-05-15 15:24:35 +0800 2019-05-1 ...