1.目录 

  • 延迟队列
  • 进一步优化

2.延迟队列

package com.redis;

import java.lang.reflect.Type;
import java.util.Set;
import java.util.UUID; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import redis.clients.jedis.Jedis; public class RedisDelayingQueue<T> {
static class TaskItem<T> {
public String id;
public T msg;
} // fastjson 序列化对象中存在 generic 类型时,需要使用 TypeReference
private Type TaskType = new TypeReference<TaskItem<T>>() {
}.getType();
private Jedis jedis;
private String queueKey; public RedisDelayingQueue(Jedis jedis, String queueKey) {
this.jedis = jedis;
this.queueKey = queueKey;
} public void delay(T msg) {
TaskItem<T> task = new TaskItem<T>();
task.id = UUID.randomUUID().toString(); // 分配唯一的 uuid
task.msg = msg;
String s = JSON.toJSONString(task); // fastjson 序列化
jedis.zadd(queueKey, System.currentTimeMillis() + , s); // 塞入延时队列 ,5s 后再试
} public void loop() {
while (!Thread.interrupted()) { // 只取一条
Set<String> values = jedis.zrangeByScore(queueKey, , System.currentTimeMillis());
if (values.isEmpty()) {
try {
Thread.sleep(); // 歇会继续
} catch (InterruptedException e) {
break;
}
continue;
}
String s = values.iterator().next();
if (jedis.zrem(queueKey, s) > ) { // 抢到了
TaskItem<T> task = JSON.parseObject(s, TaskType); // fastjson 反序列化
this.handleMsg(task.msg);
}
}
} public void handleMsg(T msg) {
System.out.println(msg);
} public static void main(String[] args) {
Jedis jedis = new Jedis();
RedisDelayingQueue<String> queue = new RedisDelayingQueue<>(jedis, "q-demo"); Thread producer = new Thread(() -> {
for (int i = ; i < ; i++) {
queue.delay("codehole" + i);
}
}); Thread consumer = new Thread(() -> queue.loop());
producer.start();
consumer.start();
try {
producer.join();
Thread.sleep();
consumer.interrupt();
consumer.join();
} catch (InterruptedException e) {
}
}
}

3.进一步优化

上面的算法中同一个任务可能会被多个进程取到之后再使用zrem进行争抢,那 些没抢到的进程都是白取了一次任务,这是浪费。可以考虑使用lua scripting来 优化一下这个逻辑,将zrangebyscore和zrem一同挪到服务器端进行原子化操 作,这样多个进程之间争抢任务时就不会出现这种浪费了

Redis(二)延迟队列的更多相关文章

  1. 基于Redis实现延迟队列

    背景 在后端服务中,经常有这样一种场景,写数据库操作在异步队列中执行,且这个异步队列是多进程运行的,这时如果对同一资源进行写库操作,很有可能产生数据被覆盖等问题,于是就需要业务层在更新数据库之前进行加 ...

  2. Redis实现延迟队列的正确姿势

    在之前探讨延时队列的文章中我们提到了 redisson delayqueue 使用 redis 的有序集合结构实现延时队列,遗憾的是 go 语言社区中并无类似的库.不过问题不大,没有轮子我们自己造. ...

  3. PHP基于Redis实现轻量级延迟队列

    延迟队列,顾名思义它是一种带有延迟功能的消息队列. 那么,是在什么场景下我才需要这样的队列呢? 一.背景 先看看一下业务场景: 1.会员过期前3天发送召回通知 2.订单支付成功后,5分钟后检测下游环节 ...

  4. 基于redis的延迟消息队列设计

    需求背景 用户下订单成功之后隔20分钟给用户发送上门服务通知短信 订单完成一个小时之后通知用户对上门服务进行评价 业务执行失败之后隔10分钟重试一次 类似的场景比较多 简单的处理方式就是使用定时任务 ...

  5. php使用redis的有序集合zset实现延迟队列

    延迟队列就是个带延迟功能的消息队列,相对于普通队列,它可以在指定时间消费掉消息. 延迟队列的应用场景: 1.新用户注册,10分钟后发送邮件或站内信. 2.用户下单后,30分钟未支付,订单自动作废. 我 ...

  6. 基于redis的延迟消息队列设计(转)

    需求背景 用户下订单成功之后隔20分钟给用户发送上门服务通知短信 订单完成一个小时之后通知用户对上门服务进行评价 业务执行失败之后隔10分钟重试一次 类似的场景比较多 简单的处理方式就是使用定时任务 ...

  7. Delayer 基于 Redis 的延迟消息队列中间件

    Delayer 基于 Redis 的延迟消息队列中间件,采用 Golang 开发,支持 PHP.Golang 等多种语言客户端. 参考 有赞延迟队列设计 中的部分设计,优化后实现. 项目链接:http ...

  8. redis(六)---- 简单延迟队列

    延迟队列的应用场景也很常见,例如:session的超时过期.自动取消未付款订单等等.redis中有一种数据结构叫做zset,即有序集合.元素类型为String类型,且元素具有唯一性不能重复,每个元素可 ...

  9. 灵感来袭,基于Redis的分布式延迟队列

    延迟队列 延迟队列,也就是一定时间之后将消息体放入队列,然后消费者才能正常消费.比如1分钟之后发送短信,发送邮件,检测数据状态等. Redisson Delayed Queue 如果你项目中使用了re ...

随机推荐

  1. 对于Redux的理解

    在移动端项目,经常会在不同view中进行传递数据,事件.当事件比较少时,我们可以通过常规的事件流方法,注册,发布事件 进行响应等等.但是项目中一个事件多处响应时候,就会使程序变得相当复杂.在现在的Vu ...

  2. HRBUST 2078:糖果(模拟,贪心)

    题不难,但作为一道恶心到了我的题,我还是记录一下的好. 题意:n个人围一圈,要求:相邻两人,分数高的要比分数低的得到更多的糖果,若分数相同则必须得到相同数量的糖果.问满足要求的最少需要分配的糖果数.( ...

  3. nrm+nvm

    一.nvm的安装和使用   nvm全称Node Version Manager是 Nodejs 版本管理器,它让我们能方便的对 Nodejs 的版 本进行切换. nvm 的官方版本只支持 Linux ...

  4. jquery鼠标点击窗口或浮动层以外关闭层【阻止冒泡事件】

    $(".up-list a.th1").click(function(){ $(this).next("ul#up-list-ul").show(); }); ...

  5. [Python Cookbook] Numpy Array Joint Methods: Append, Extend & Concatenate

    数组拼接方法一 思路:首先将数组转成列表,然后利用列表的拼接函数append().extend()等进行拼接处理,最后将列表转成数组. 示例1: import numpy as np a=np.arr ...

  6. TensorFlow——tensorflow指定CPU与GPU运算

    1.指定GPU运算 如果安装的是GPU版本,在运行的过程中TensorFlow能够自动检测.如果检测到GPU,TensorFlow会尽可能的利用找到的第一个GPU来执行操作. 如果机器上有超过一个可用 ...

  7. Java爬虫系列三:使用Jsoup解析HTML

    在上一篇随笔<Java爬虫系列二:使用HttpClient抓取页面HTML>中介绍了怎么使用HttpClient进行爬虫的第一步--抓取页面html,今天接着来看下爬虫的第二步--解析抓取 ...

  8. 【webpack2】-- 入门与解析

    每次学新东西总感觉自己是不是变笨了,看了几个博客,试着试着就跑不下去,无奈只有去看官方文档. webpack是基于node的.先安装最新的node. 1.初始化 安装node后,新建一个目录,比如ht ...

  9. Android Framework 记录之一

    简介 之前的研究太偏向应用层功能实现了,很多原理不了解没有深究,现在研究framework框架层了. 记录 1.下载源码,目录如下: 2.Android系统的层次如下: 3.项目目录简单分析如下: 4 ...

  10. 【spring boot】5.spring boot 创建web项目并使用jsp作前台页面

    贼烦的是,使用spring boot 创建web项目,然后我再idea下创建的,but 仅仅启动spring boot的启动类,就算整个项目都是好着的,就算是能够进入controller中,也不能成功 ...