用redis做简单的任务队列(一)
队列本身其实是个有序的列表,而Redis是支持list的,我们可以查看Redis的官方文档 http://redis.io/commands#list,其中我们可以对这个队列的两端分别进行操作,所以其实Redis中的list即可以当做普通的先进先出的queue,也可以作为先进后出的stack。
如果当做队列来用,我们可以用LPUSH(头部插入)和RPOP(尾部弹出)或RPUSH(尾部插入)和LPOP(头部弹出),这两种方式都可以,只要是搭配使用即可。但我们平时一般搭配使用 LPUSH和RPOP。
一般开发的时候我们会分为生产者和消费者,生产者生产消息,消费者获取消息进行处理。
Producer:
redis->lpush(‘joblist’, ‘this is Job-1’);
redis->lpush(‘joblist’, ‘this is Job-2’);
….
Cosumer:
job = redis->rpop(‘joblist’);// return Job-1
done the job….
job = redis->rpop(‘joblist’);// return Job-2
done the job…
正常情况下上面这些都是没问题的,但是我们也经常遇到这种情况,当任务进行到一半(即任务没有完全执行完)的时候,突然服务器宕机或者网络中断,这时候任务其实是没有真正完成的,这时候出现队列中的任务“丢失”了,并不是说队列任务真的丢失了,而是我们把任务从队列拿出来之后并没有完成这个任务,这时候我们就需要考虑如何能在任务真正完成的时候才把任务从队列中删除。
幸运地是,redis其实给我们提供了这样的可能。继续翻看redis的官方文档,我们发现 RPOPLPUSH,从字面含义来解释就是尾部弹出头部插入,它后面跟两个参数,一个是弹出的list,一个是要插入的list,而且文档上告诉我们它可以实现 可靠的队列。我们可以把任务从队列中取出来放到另外一个执行中的队列,等到任务真正完成之后再从执行中的队列中删除。
那么上面的代码我们可以修改成如下,producer不变:
Cosumer:
job = redis->rpoplpush(‘joblist’, ‘job-doing’);// 把Job-1从joblist转移到job-doing
done the job….// 完成Job-1
redis->lrem(‘job-doing’, 1, job);// 等Job-1完成之后把它从job-doing队列中删除
这样如果Job失败,那Job的任务还存在在队列job-doing中,我们可以单独启一个进程来扫描job-doing列表,如果一个job长时间在队列中,则重新执行该Job或重新插入的job列表。
当然,这也不是完全100%靠谱的解决方案,因为如果存在很多相同的job,那我们从job-doing删除job的时候就无法确认是哪个job真正应该删除,但是像我们上面描述的,既然Job是相同的,那我们删除哪个也无所谓了,反正执行的结果都一样。上面的解决方案还有一个问题,我们必须要长时间地监控job-doing列表,这需要额外的资源,还有一种方式是job-doing和job用同一个列表,即:
Cosumer:
job = redis->rpoplpush(‘joblist’, ‘jobllist’); 把Job-1从joblist尾部转移到joblist头部
done the job….// 完成Job-1
redis->lrem(‘job-doing’, 1, job);// 等Job-1完成之后把它从joblist头部删除
其实,文章写到这里,大家应该明白了,这样一来,我们利用循环队列,即可实现可靠的队列。当然,相比较世面上比较成熟的队列,例如 RabbitMQ、 Beanstalkd、 IronMQ等还是有很多的不足,但是如果是简单地项目或者项目本身就已经在使用redis又不想添加新的组件,试试redis list也不错。
用redis做简单的任务队列(一)的更多相关文章
- 用redis做简单的任务队列(二)
是用redis做任务队列时,要思考: 用什么数据类型来做任务队列 怎样才能防止重复爬取 上一篇文章已经决定使用list来做任务队列,但是去重问题没有得到解决.这里可以用set来解决思考二的问题,就是防 ...
- 程序员修神之路--redis做分布式锁可能不那么简单
菜菜哥,复联四上映了,要不要一起去看看? 又想骗我电影票,对不对? 呵呵,想去看了叫我呀 看来你工作不饱和呀 哪有,这两天我刚基于redis写了一个分布式锁,很简单 不管你基于什么做分布式锁,你觉得很 ...
- 使用Redis做MyBatis的二级缓存
使用Redis做MyBatis的二级缓存 通常为了减轻数据库的压力,我们会引入缓存.在Dao查询数据库之前,先去缓存中找是否有要找的数据,如果有则用缓存中的数据即可,就不用查询数据库了. 如果没有才去 ...
- redis 的简单命令
以下实例讲解了如何启动 redis 客户端: 启动 redis 客户端,打开终端并输入命令 redis-cli.该命令会连接本地的 redis 服务. $redis-cli redis > re ...
- spring-boot集成mybatis,用redis做缓存
网上有很多例子了,执行源码起码有3个,都是各种各样的小问题. 现在做了个小demo,实现spring-boot 用redis做缓存的实例,简单记录下思路,分享下源码. 缓存的实现,分担了数据库的压力, ...
- 使用Redis做分布式
一 为什么使用 Redis 在项目中使用 Redis,主要考虑两个角度:性能和并发.如果只是为了分布式锁这些其他功能,还有其他中间件 Zookpeer 等代替,并非一定要使用 Redis. 性能: 如 ...
- NetCore入门篇:(九)Net Core项目使用Session及用Redis做分布式
一.简介 1.因为Net Core默认是没有启动Session功能的,如果需要使用,需要通过代码开启. 2.本篇说明如果启用默认Session实现,即Session存到内存中. 3.本篇扩展说明如何用 ...
- Redis的简单了解以及主从复制
1.Redis的简单了解 Redis是一种高性能的分布式NoSql数据库,持久存储,高并发,数据类型丰富,通过现场申请内存空间,同时可以配置虚拟内存.五种数据类型:string(字符串,这种格式和me ...
- Redis主从复制简单介绍
由于本地环境的使用,所以搭建一个本地的Redis集群,本篇讲解Redis主从复制集群的搭建,使用的平台是Windows,搭建的思路和Linux上基本一致! (精读阅读本篇可能花费您15分钟,略读需5分 ...
随机推荐
- 解决Eclipse 项目报错:Unbound classpath container: ‘JRE System Library [JavaSE-1.7]
MyEclipse出现下面两条报错: The project cannot be built until build path errors are resolved HelloWord Unknow ...
- mysql 对比两个表的一致性
-- A和B两个表 数据是否一致select 自定义 from A left join B on A.id = B.id where B.id is null 注释:这样查询的结果是A表中有而B表中没 ...
- 基于Java的三种对象持久化方式
1:序列化技术: 序列化的过程就是将对象写入字节流和从字节流中读取对象.将对象状态转换成字节流之后,可以用java.io包中的各种字节流类将其保存到文件中,可以通过管道或线程读取,或通过网络连接将对象 ...
- 性能测试 tps持续走低,响应时间持续增加,瓶颈分析
吞吐量图如上 响应时间图如上 自身压测的机器,资源使用率并没有饱和 服务器,top命令下看到load average的值很低,本身是4核的server. 每个核的CPU使用率也极低,空闲cpu占95+ ...
- Selenium UI自动化测试 Selenium Automatic Testing
https://www.cnblogs.com/sunada2005/archive/2013/12/22/3486314.html UI Automatic Testing 1. 什么样的项目适合自 ...
- Android JNI学习(二)——实战JNI之“hello world”
本系列文章如下: Android JNI(一)——NDK与JNI基础 Android JNI学习(二)——实战JNI之“hello world” Android JNI学习(三)——Java与Nati ...
- Android开机广播和关机广播
有些时候我们需要我们的程序在系统开机后能自动运行,这个时候我们可以使用Android中的广播机制,编写一个继承BroadcastReceiver的类,接受系统启动关闭广播.代码如下: /** *@au ...
- 查询ORACLE存储关联表
SELECT DISTINCT * FROM user_sourceWHERE TYPE = 'PROCEDURE'AND upper(text) LIKE '%PS_KL_ABS_002_DATA% ...
- English trip -- Phonics 2 元音字母a
xu言: 欲速则不达,如果这是你生命中最后一天.你还愿意花这么多精力继续坚持你现在做的事吗?如果答案是否定的,那么你需要改变了! What makes a word? 单词构成 Word 单词: ...
- codeforces 578b//"Or" Game// Codeforces Round #320 (Div. 1)
题意:n个数字,最多操作k次,每次乘x,要使结果数组的与值最大. 能推断出结果是对一个元素操作k次,并且这个元素的二进制最高位比较大.并不一定是取最大的,比如1100和1010,乘以一次2,两种选法分 ...