写在前面: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命令让线程停下来。更好的做法是通过blpop和brpop代替之前的lpop和rpop,即用阻塞读(在队列没有数据时,立即进入休眠状态;当数据到来,立刻重新请求)的方式,解决因为sleep命令带来的延迟。

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

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

2.延时队列

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

在Redis中延时队列的实现是由zset(有序列表)来实现,基本使用方式为zset key score value。在延时队列中常常把消息序列化成一个字符串作为 zset 的value,消息的过期时间作为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. http://edu.manew.com/ ,蛮牛教育(很少免费),主要是unty3D和大数据方向。适合扫盲

    http://edu.manew.com/ ,蛮牛教育(很少免费),主要是unty3D和大数据方向.

  2. Vue入坑——vue-cli(脚手架)目录结构认识

    转载:https://my.oschina.net/u/3802541/blog/1809182 一.目录结构 |-- build                            // 项目构建 ...

  3. QT 在QTabWidget中设置一些调色板

    这次所做的项目中需要用到如下功能,点击tableWidget中的子项,将会弹出颜色选值对话框,实现子项的改变,如下图所示: 1.首先,将自己定制的调色板放入tableWidget中 for (int ...

  4. git -- 项目开发最常用操作记录

    官方Git - Book https://git-scm.com/book/zh/v2 ------------------------------git配置以及公钥生成--------------- ...

  5. minifilter 算是总结吧

    FltRegisterFilter 注册过滤器 FltStartFiltering 开始过滤 InstatanceSetupCallback 实例安装回调 .当一个微过滤器加载的时候,每个存在的卷都会 ...

  6. 转为win64后, MS的lib问题

         >   正在创建库 C:\Users\Administrator\Desktop\branch-Unicode-156\\Temp\Link\PointCloudMeasure\x64 ...

  7. (转)FastCgi与PHP-fpm之间是个什么样的关系

    首先,CGI是干嘛的?CGI是为了保证web server传递过来的数据是标准格式的,方便CGI程序的编写者. web server(比如说nginx)只是内容的分发者.比如,如果请求/index.h ...

  8. Codeforces Round #478 Div2 975A 975B 975C 975D

    A. Aramic script 题目大意:   对于每个单词,定义一种集合,这个集合包含且仅包含单词中出现的字母.给你一堆单词,问有多少种这种集合. 题解:   状压,插入set,取size #in ...

  9. Leetcode92. Reverse Linked List II反转链表

    反转从位置 m 到 n 的链表.请使用一趟扫描完成反转. 说明: 1 ≤ m ≤ n ≤ 链表长度. 示例: 输入: 1->2->3->4->5->NULL, m = 2 ...

  10. 在DataWorks中实现指定UDF只能被指定账户访问

    背景 之前写过一篇文章是关于“DataWorks和MaxCompute内部权限体系的区别”有兴趣的朋友可以点击阅读查看详情.但是还是有些同学会问,我如何在DataWorks中实现我的具体某个Resou ...