您的位置:首页 > 娱乐 > 明星 > 电商首页设计_seo营销推广公司_南昌百度快速排名提升_新闻近期大事件

电商首页设计_seo营销推广公司_南昌百度快速排名提升_新闻近期大事件

2025/7/22 17:14:08 来源:https://blog.csdn.net/weixin_43833540/article/details/148763750  浏览:    关键词:电商首页设计_seo营销推广公司_南昌百度快速排名提升_新闻近期大事件
电商首页设计_seo营销推广公司_南昌百度快速排名提升_新闻近期大事件

一、基于 Redis 键空间通知(适合精确延时任务)

原理:利用 Redis 的键过期事件(EXPIRE)触发任务执行,通过监听 __keyevent@*__:expired 通道捕获事件。
步骤

  1. 启用 Redis 键空间通知(redis.conf 或运行时配置):

    CONFIG SET notify-keyspace-events Ex
    
  2. Spring Boot 监听器实现

    @Component
    public class KeyExpiredListener extends KeyExpirationEventMessageListener {public KeyExpiredListener(RedisMessageListenerContainer listenerContainer) {super(listenerContainer);}@Overridepublic void onMessage(Message message, byte[] pattern) {String expiredKey = new String(message.getBody());if (expiredKey.startsWith("task:")) { // 过滤业务键System.out.println("执行任务: " + expiredKey);// 例如:task:123 过期时执行订单超时逻辑}}
    }
    
  3. 注册监听器

    @Configuration
    public class RedisConfig {@BeanRedisMessageListenerContainer container(RedisConnectionFactory factory, KeyExpiredListener listener) {RedisMessageListenerContainer container = new RedisMessageListenerContainer();container.setConnectionFactory(factory);container.addMessageListener(listener, new PatternTopic("__keyevent@*__:expired"));return container;}
    }
    
  4. 调度任务(设置带过期时间的键):

    @Service
    public class TaskScheduler {@Autowiredprivate StringRedisTemplate redisTemplate;public void scheduleTask(String taskId, long delaySeconds) {redisTemplate.opsForValue().set("task:" + taskId, "data", delaySeconds, TimeUnit.SECONDS); // 键在 delaySeconds 秒后过期}
    }
    

注意:需在 Redis 配置中开启 notify-keyspace-events Ex


二、基于 Redis 有序集合轮询(适合批量定时任务)

原理:将任务执行时间作为 ZSETscore,通过定时任务查询到期的任务并执行。
步骤

  1. 添加任务到 ZSET

    public void addTask(String taskId, Instant executeTime) {stringRedisTemplate.opsForZSet().add("scheduled_tasks", taskId, executeTime.getEpochSecond());
    }
    
  2. 定时扫描并执行任务(每分钟轮询):

    @Scheduled(cron = "0 * * * * *") // 每分钟执行
    public void pollTasks() {long now = Instant.now().getEpochSecond();Set<String> tasks = stringRedisTemplate.opsForZSet().rangeByScore("scheduled_tasks", 0, now); // 获取所有到期任务for (String task : tasks) {System.out.println("执行任务: " + task);// 执行后移除任务stringRedisTemplate.opsForZSet().remove("scheduled_tasks", task);}
    }
    

优点:避免键空间通知的丢失风险,适合任务量大的场景。


三、基于 Redis 分布式锁(防集群任务重复执行)

原理:在分布式环境中,通过 Redis 锁确保同一时间只有一个实例执行定时任务。
代码示例

@Component
public class DistributedTask {@Autowiredprivate StringRedisTemplate redisTemplate;private static final String LOCK_KEY = "TASK_LOCK:ORDER_CLEAN";@Scheduled(cron = "0 0 3 * * ?") // 每天凌晨3点执行public void dailyTask() {Boolean locked = redisTemplate.opsForValue().setIfAbsent(LOCK_KEY, "locked", Duration.ofMinutes(10));if (Boolean.TRUE.equals(locked)) {try {cleanExpiredOrders(); // 执行核心任务} finally {redisTemplate.delete(LOCK_KEY); // 释放锁(可选)}}}
}

关键点

  • 使用 setIfAbsent 原子操作获取锁,避免并发冲突。
  • 锁自动过期防止死锁(如任务执行超时)。

​​版本要求​​:
​​Spring Data Redis ≥ 2.3.0​​:该版本引入了 setIfAbsent(key, value, duration) 方法,支持​​原子性设置键值+过期时间​​(对应 Redis 的 SET key value NX EX seconds 命令)


四、方案对比

方案适用场景注意事项
键空间通知精确延时任务(如30分钟后关单)需配置 Redis,事件可能丢失
有序集合轮询批量任务、高可靠性场景需自行处理任务分页和重试
分布式锁集群环境防重复执行(如日报生成)锁超时时间需大于任务执行时间

*补充

  • 关键业务(如支付超时)建议结合 数据库日志+重试机制 补偿;
  • 高频任务优先选 ZSET 轮询,避免键空间通知的性能瓶颈;
  • 分布式锁的锁键需包含业务标识(如 LOCK_KEY:业务名)。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com