Redis学习笔记02-消息队列与延时队列
写在前面: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-消息队列与延时队列的更多相关文章
- Redis学习笔记~实现消息队列比MSMQ更方便
什么是队列:简单的说就是数据存储到一个空间里(可以是内存,也可以是物理文件),先存储的数据对象,先被取出来,这与堆栈正好相反,消息队列也是这样,将可能出现高并发的数据进行队列存储,并按着入队的顺序依次 ...
- redis学习笔记-02:为什么使用NoSQL数据库
一.第一代:单机版的MySQL 1.静态网页,动态交互类型的网站不多. 2.架构:APP---->DAL---->MySQL Instance 3.数据存储的瓶颈: (1)数据量总大小超过 ...
- redis学习笔记-02 list列表类型命令
一.lpush key value1 value2 value3 value4(命令将一个或多个值插入到列表头部. 如果 key 不存在,一个空列表会被创建并执行 LPUSH 操作) lpush k1 ...
- Redis学习笔记~目录
回到占占推荐博客索引 百度百科 redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合). ...
- Redis:学习笔记-02
Redis:学习笔记-02 该部分内容,参考了 bilibili 上讲解 Redis 中,观看数最多的课程 Redis最新超详细版教程通俗易懂,来自 UP主 遇见狂神说 4. 事物 Redis 事务本 ...
- Linux进程间通信IPC学习笔记之消息队列(SVR4)
Linux进程间通信IPC学习笔记之消息队列(SVR4)
- Redis学习笔记4-Redis配置详解
在Redis中直接启动redis-server服务时, 采用的是默认的配置文件.采用redis-server xxx.conf 这样的方式可以按照指定的配置文件来运行Redis服务.按照本Redi ...
- Redis学习笔记4-Redis配置具体解释
在Redis中直接启动redis-server服务时, 採用的是默认的配置文件.採用redis-server xxx.conf 这种方式能够依照指定的配置文件来执行Redis服务. 依照本Redi ...
- Redis学习笔记八:集群模式
作者:Grey 原文地址:Redis学习笔记八:集群模式 前面提到的Redis学习笔记七:主从复制和哨兵只能解决Redis的单点压力大和单点故障问题,接下来要讲的Redis Cluster模式,主要是 ...
- redis学习笔记(详细)——高级篇
redis学习笔记(详细)--初级篇 redis学习笔记(详细)--高级篇 redis配置文件介绍 linux环境下配置大于编程 redis 的配置文件位于 Redis 安装目录下,文件名为 redi ...
随机推荐
- iOS开发之SceneKit框架--SCNView.h
1.SCNView 在macOS中,SCNView是NSView的子类,在iOS和tvOS中,SCNView是UIView的子类.SCNView用于显示SceneKit的3D场景,而需要设置场景的相关 ...
- ssm项目中使用拦截器加上不生效解决方案
在很多时候,需要拦截器来帮助我们完成一些特定的工作,比如获取请求的参数,本身在request这种获取数据就是一次磁盘的io, 如果在filter中获取了参数,那么在controller中就不能获取相关 ...
- python基础语法(运算符及优先级)
python基础语法(运算符及优先级) python语言支持的运算符类型 算数运算符 假设变量a为10,变量b为21 算数符 描述 实例 + 加-两个对象相加 a+b结果31 - 减-得到一个负数或者 ...
- 杂项-关于strlen()的使用
发现了一个很坑的东西. 看下面两份代码: //code1 char s[N]; ;i<strlen(s);i++)Do(); //code2 char s[N]; ;s[i];i++)Do(); ...
- Loadrunner安装与破解【转】
Loadrunner安装与破解 一.下载 我的LoadRunner 11下载地址是: http://pan.baidu.com/s/1qYFy2DI 二.安装 1.启动安装程序 运行setup.exe ...
- thinkphp 视图定义
视图定义 视图通常是指数据库的视图,视图是一个虚拟表,其内容由查询定义.同真实的表一样,视图包含一系列带有名称的列和行数据.但是,视图并不在数据库中以存储的数据值集形式存在.行和列数据来自由定义视图的 ...
- 2-sat——hdu3062
对于怎么建边还是不太清楚 选了a,那么b c不选,所以连边 选了b或c,那么a必定不选 /* 每个点拆成i*2,i*2+1 队长选,那么队友不选 队长不选,那么队友必定要选 */ #include&l ...
- 在vc2008 mfcC++中使用sqlite的示例
http://owlman.org/?p=890 在C++中使用sqlite的示例 2011年8月5日admin发表评论阅读评论 最近因为工作原因,终于使我有机会腾出时间来接触了一下SQLite数据库 ...
- splay区间翻转
原题P3391 [模板]文艺平衡树(Splay) 题目背景 这是一道经典的Splay模板题——文艺平衡树. 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: ...
- centos 以太坊多节点私链搭建
环境 centos 7 搭建 3 个节点的 私链. 第一步 安装 一些依赖的 工具 yum update -y && yum install git wget bzip2 vim ...