基于Redis-keyspaceNotification实现的过期事件

一:业务场景

在实际场景中,会遇到生成订单过30分钟或15分钟取消等等业务。
第一种方法数据库轮询 (消耗数据库性能
第二种方法:基于JDK-DelayQueue实现的延迟队列(重启队列数据全消失)
第三种方法:使用定时任务隔断时间去查(浪费性能
第三种方法:基于Redis-keyspaceNotification实现的过期事件
第四种方法:使用消息队列

二:实现思路

生成订单时,向 Redis增加一个 KV 键值对,K 为订单号,保证通过 K 能定位到数据库中的某个订单即可,V 可为任意值。因为过期取消的键值对,只拿得到key,拿不到value。并且在支付成功时,回调接口修改状态可以把对应的key删掉。

三:代码实现

继承KeyExpirationEventMessageListener 类:监听,过期会回调

@Component
public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {


    public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
        super(listenerContainer);
    }

	@Override
	public void onMessage(Message message, byte[] bytes) {
		//key过期监听
        System.out.println("开始执行过期事件");

        //获取过期的key
        String expireKey = message.toString();

        //赛事订单取消
        if(expireKey.contains("apply:competitiong:")) {
            expireKey = expireKey.replace("apply:competitiong:", "");
            String orderId = expireKey;
            sysCompetitionApplyService.doDelayQueue(Long.valueOf(orderId));
            System.out.println("redis取消赛事订单");
        }

        //赛事定级取消
        if(expireKey.contains("apply:rank:")) {
            expireKey = expireKey.replace("apply:rank:", "");
            String orderId = expireKey;
            sysRankApplyService.doDelayQueueRank(Long.valueOf(orderId));
            System.out.println("redis取消定级订单");
        }
            //信息打印
        System.out.println("失效的key"+expireKey);


    }
}

redis工具类

@Component
public class RedisService
{
    @Autowired
    public Redistemplate redistemplate;

    /**
     * 缓存基本的对象,Integer、String、实体类等
     *
     * @param key 缓存的键值
     * @param value 缓存的值
     */
    public <T> void setCacheObject(final String key, final T value)
    {
        redistemplate.opsForValue().set(key, value);
    }

    /**
     * 缓存基本的对象,Integer、String、实体类等
     *
     * @param key 缓存的键值
     * @param value 缓存的值
     * @param timeout 时间
     * @param timeUnit 时间颗粒度
     */
    public <T> void setCacheObject(final String key, final T value, final Long timeout, final TimeUnit timeUnit)
    {
        redistemplate.opsForValue().set(key, value, timeout, timeUnit);
    }

    /**
     * 设置有效时间
     *
     * @param key Redis键
     * @param timeout 超时时间
     * @return true=设置成功;false=设置失败
     */
    public boolean expire(final String key, final long timeout)
    {
        return expire(key, timeout, TimeUnit.SECONDS);
    }

    /**
     * 设置有效时间
     *
     * @param key Redis键
     * @param timeout 超时时间
     * @param unit 时间单位
     * @return true=设置成功;false=设置失败
     */
    public boolean expire(final String key, final long timeout, final TimeUnit unit)
    {
        return redistemplate.expire(key, timeout, unit);
    }

}

业务实现

        // 设置15分钟取消订单
        String redisKey = String.valueOf(StrUtil.format("{}{}",
                "apply:competitiong:", sysCompetitionApply.getApplyId()));
        redisService.setCacheObject
        (redisKey,sysCompetitionApply.getApplyId() ,15L, TimeUnit.MINUTES);
     // 设置15分钟取消订单 ,key随便设置
        String redisKey = String.valueOf(StrUtil.format("{}{}",
                "apply:rank:", sysRankApply.getApplyId()));
        redisService.setCacheObject
        (redisKey,sysRankApply.getApplyId() , 15L, TimeUnit.MINUTES);

TimeUnit.DAYS 日
TimeUnit.HOURS 时
TimeUnit.MINUTES 分
TimeUnit.SECONDS 秒
TimeUnit.MILLISECONDS 毫秒

相关文章

显卡天梯图2024最新版,显卡是电脑进行图形处理的重要设备,...
初始化电脑时出现问题怎么办,可以使用win系统的安装介质,连...
todesk远程开机怎么设置,两台电脑要在同一局域网内,然后需...
油猴谷歌插件怎么安装,可以通过谷歌应用商店进行安装,需要...
虚拟内存这个名词想必很多人都听说过,我们在使用电脑的时候...