Redis模拟延时队列实现日程提醒的方法
使用Redis模拟延时队列
实际上通过MQ实现延时队列更加方便,只是在实际业务中种种原因导致最终选择使用redis作为该业务实现的中间件,顺便记录一下。
该业务是用于日程短信提醒,用户添加日程后,就会被放入redis队列中等待被执行发送短信提醒业务。
本文介绍如何使用Redis来实现一个简单的延时任务队列,通过这个示例,可以帮助你理解如何利用Redis的有序集合特性来管理和执行延时任务。
设计思路
Redis有序集合(Sorted Set)可以很好地用来实现延时队列的功能。通过将任务的执行时间作为分数(score)来存入有序集合中,并定期检查集合中小于等于当前时间的任务来触发执行。
代码实现
JedisCluster连接初始化
首先,我们需要初始化JedisCluster连接来与Redis集群进行交互。
private static final String ZSET_KEY = "sms_delayed_tasks"; private JedisCluster jedisCluster; public void RedisClusterScheduler() { Set<HostAndPort> nodes = new HashSet<>(); //从配置文件中读取redis集群配置 for (String node : AcpCore.getProp("spring.redis.cluster.nodes").split(",")) { String[] hostPort = node.split(":"); nodes.add(new HostAndPort(hostPort[0], Integer.parseInt(hostPort[1]))); } GenericObjectPoolConfig<Jedis> poolConfig = new GenericObjectPoolConfig<>(); poolConfig.setMaxTotal(128); poolConfig.setMaxIdle(128); poolConfig.setMinIdle(16); jedisCluster = new JedisCluster(nodes, 2000, 2000, 5, AcpCore.getProp("spring.redis.password"), poolConfig); if (!isCalled) { isCalled = true; startTaskChecker(); } }
添加延时任务
我们可以通过指定任务和执行时间来添加延时任务。该方法将执行时间转换为时间戳,并将任务存储在Redis有序集合中。
public void addDelayedTask(String task, String time) { long executeTime = convertToTimestamp(time); if (executeTime > System.currentTimeMillis() / 1000) { jedisCluster.zadd(ZSET_KEY, executeTime, task); log.info("添加任务: " + task + " 执行时间: " + executeTime); } else { log.info("任务时间必须在当前时间之后: " + task); } } private long convertToTimestamp(String time) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); try { return sdf.parse(time).getTime() / 1000; } catch (ParseException e) { e.printStackTrace(); return System.currentTimeMillis() / 1000; } }
检查和执行任务
通过一个定时任务不断检查当前时间之前的任务并执行。
private void startTaskChecker() { executorService.submit(() -> { while (!Thread.currentThread().isInterrupted()) { try { checkAndExecuteTasks(); Thread.sleep(1000); } catch (Exception e) { log.info(new Date() + "发生异常但不中断,异常是:" + e); } } }); } private void checkAndExecuteTasks() { long currentTime = System.currentTimeMillis() / 1000; Set<String> tasks = jedisCluster.zrangeByScore(ZSET_KEY, 0, currentTime); for (String task : tasks) { jedisCluster.zrem(ZSET_KEY, task); executeTask(task); } }
执行任务的逻辑
假设任务内容是一个JSON对象,执行逻辑在这里可以是任何操作,比如调用外部服务、发送消息等。
private void executeTask(String taskJson) { JSONObject task = JSONObject.parseObject(taskJson); // 在此处添加具体的业务逻辑 log.info("执行任务: " + task); }
总结
通过Redis的有序集合和简单的定时器,能够实现一个简洁有效的延时任务队列。
当然,这个示例是一个简化的模型,在生产环境中,你需要考虑任务的幂等性、系统崩溃后的恢复策略、任务的优先级等问题。希望本文能为你提供实现延时队列的思路和参考。
到此这篇关于Redis模拟延时队列 实现日程提醒的文章就介绍到这了,更多相关Redis延时队列内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
详解redis在服务器linux下启动的相关命令(安装和配置)
这篇文章主要介绍了redis在服务器linux下的启动的相关命令(安装和配置),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下2022-08-08SpringSession+Redis实现集群会话共享的方法
为了保证WEB应用的承载能力, 需要对WEB应用进行集群处理.这篇文章主要介绍了SpringSession+Redis实现集群会话共享的方法,需要的朋友参考下吧2018-08-08Redis序列化设置以及jetcache连接Redis序列化的设置过程
这篇文章主要介绍了Redis序列化设置以及jetcache连接Redis序列化的设置过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教2023-12-12Redis 异常 read error on connection 的解决方案
这篇文章主要介绍了Redis异常read error on connection的解决方案,文章围绕主题展开详细的内容介绍,具有一定的参考价值,感兴趣的小伙伴可以参考一下2022-08-08
最新评论