队列本身其实是个有序的列表,而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做简单的任务队列(一)的更多相关文章

  1. 用redis做简单的任务队列(二)

    是用redis做任务队列时,要思考: 用什么数据类型来做任务队列 怎样才能防止重复爬取 上一篇文章已经决定使用list来做任务队列,但是去重问题没有得到解决.这里可以用set来解决思考二的问题,就是防 ...

  2. 程序员修神之路--redis做分布式锁可能不那么简单

    菜菜哥,复联四上映了,要不要一起去看看? 又想骗我电影票,对不对? 呵呵,想去看了叫我呀 看来你工作不饱和呀 哪有,这两天我刚基于redis写了一个分布式锁,很简单 不管你基于什么做分布式锁,你觉得很 ...

  3. 使用Redis做MyBatis的二级缓存

    使用Redis做MyBatis的二级缓存 通常为了减轻数据库的压力,我们会引入缓存.在Dao查询数据库之前,先去缓存中找是否有要找的数据,如果有则用缓存中的数据即可,就不用查询数据库了. 如果没有才去 ...

  4. redis 的简单命令

    以下实例讲解了如何启动 redis 客户端: 启动 redis 客户端,打开终端并输入命令 redis-cli.该命令会连接本地的 redis 服务. $redis-cli redis > re ...

  5. spring-boot集成mybatis,用redis做缓存

    网上有很多例子了,执行源码起码有3个,都是各种各样的小问题. 现在做了个小demo,实现spring-boot 用redis做缓存的实例,简单记录下思路,分享下源码. 缓存的实现,分担了数据库的压力, ...

  6. 使用Redis做分布式

    一 为什么使用 Redis 在项目中使用 Redis,主要考虑两个角度:性能和并发.如果只是为了分布式锁这些其他功能,还有其他中间件 Zookpeer 等代替,并非一定要使用 Redis. 性能: 如 ...

  7. NetCore入门篇:(九)Net Core项目使用Session及用Redis做分布式

    一.简介 1.因为Net Core默认是没有启动Session功能的,如果需要使用,需要通过代码开启. 2.本篇说明如果启用默认Session实现,即Session存到内存中. 3.本篇扩展说明如何用 ...

  8. Redis的简单了解以及主从复制

    1.Redis的简单了解 Redis是一种高性能的分布式NoSql数据库,持久存储,高并发,数据类型丰富,通过现场申请内存空间,同时可以配置虚拟内存.五种数据类型:string(字符串,这种格式和me ...

  9. Redis主从复制简单介绍

    由于本地环境的使用,所以搭建一个本地的Redis集群,本篇讲解Redis主从复制集群的搭建,使用的平台是Windows,搭建的思路和Linux上基本一致! (精读阅读本篇可能花费您15分钟,略读需5分 ...

随机推荐

  1. vim的几个插件mark.vim ctrlp.vim等

    开发过程中, 保证语义的前提下, 尽量使用 短的 变量名: 如: 用 $map来代替 $condition, 因为在书写长的变量名的时候, 容易写错, 而排查错误, 还不容易找出来. vim在浏览和排 ...

  2. Ubuntu上 配置Eclipse:安装CDT

    在最新的 Ubuntu Kylin 16.04 中安装了eclipse,在纠结了很久的网络问题之后,开始了eclipse的配置以便在上面运行ns3. 在官方网站上安装完 eclipse LUNA 之后 ...

  3. HDU 1083 Courses(二分图匹配模板)

    http://acm.hdu.edu.cn/showproblem.php?pid=1083 题意:有p门课和n个学生,每个学生都选了若干门课,每门课都要找一个同学来表演,且一个同学只能表演一门课,判 ...

  4. pyHook监听用户鼠标、键盘事件

    一.代码部分:获取用户输入信息,并与截图一起保存到XX目录下   # -*- coding: utf-8 -*- #   import pythoncom import pyHook    impor ...

  5. indexedDB入门

    localforage localStorage局限性:存储容量限制,仅支持字符串,如果是存对象还需要将使用JSON.stringify和JSON.parse方法互相转换:读取都是同步的.大多数情况o ...

  6. Unity + NGUI 实现人物头顶UI的信息展示

    1.思路: (1)信息数据:需要展示属性信息 (2)信息的展示:负责显示UI属性信息 (3)UI的跟随:负责实现UI对人物的跟随 (4)UI的管理:负责对UI进行创建于回收,游戏中需要用到UI的地方都 ...

  7. vue.js循环for(列表渲染)详解

    vue.js循环for(列表渲染)详解 一.总结 一句话总结: v-for <ul id="example-1"> <li v-for="item in ...

  8. yii新手在实例化models(controller调用models实化化)php warning错误

    新手在执照yii教程来的时候,config/main.php文件是全新写的,post提交的时候,会出错 include(LoginForm.php) [<a href='function.inc ...

  9. jsp post/get中接处理

    jsp post/get中接处理 以参数:username为便 post接收中文比get接收中文要方便多了. <%@ page contentType="text/html;chars ...

  10. Silverlight自定义控件系列 – TreeView (1)

      原文路径:http://blog.csdn.net/wlanye/article/details/7265457 很多人都对MS自带的控件不太满意(虽然MS走的是简约风格),都会试图去修改或创建让 ...