redis 延时队列

实现思路 

方式一 

1. 使用redis zset 数据结构   2.使用score排序   score为过期时间点   3.启动线程不断取出排序第一个  比较score和当前时间点   如果score小于或等于当前时间  说明此数据过期  需要处理  4.处理完毕在zset中移除

public class TestMain {
    private static final String ADDR="39.96.77.182";
    private static final int PORT=6379;
    //初始化jedis
    private static JedisPool jedisPool=new JedisPool(new GenericObjectPoolConfig(),ADDR,PORT,10000);
    public static Jedis getJedis() {
        return jedisPool.getResource();
    }
    //消息入队
    public void productionDelayMessage(){
        //延迟5秒
        Calendar cal1 = Calendar.getInstance();
        cal1.add(Calendar.SECOND, 5);
        int second3later = (int) (cal1.getTimeInMillis() / 1000);
        Long orderId = TestMain.getJedis().zadd("OrderId", second3later, "OID0000001" );
        System.out.println(new Date()+"ms:redis生成了一个订单任务:订单ID为"+"OID0000001"+"==============="+orderId);
    }
    //消费者取订单
    public void consumerDelayMessage(){
        Jedis jedis = TestMain.getJedis();
        while(true){
            Set<Tuple> items = jedis.zrangeWithScores("OrderId", 0, 1);
            if(items == null || items.isEmpty()){
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                continue;
            }
            int  score = (int) ((Tuple)items.toArray()[0]).getScore();
            Calendar cal = Calendar.getInstance();
            int nowSecond = (int) (cal.getTimeInMillis() / 1000);
            if(nowSecond >= score){
                String orderId = ((Tuple)items.toArray()[0]).getElement();
                Long num = jedis.zrem("OrderId", orderId);
                System.out.println(num);
                if( num != null && num>0){
                    System.out.println(new Date() +"ms:redis消费了一个任务:消费的订单OrderId为"+orderId);
                }

            }
        }
    }

    

    public static void main(String[] args) {
        TestMain appTest =new TestMain();
        appTest.productionDelayMessage();
        appTest.consumerDelayMessage();
    }

  执行结果

 

方式二:  redis过期回调

修改redis 配置 redis.conf   添加notify-keyspace-events Ex

编写测试demo 

新建boot工程 加入redis依赖

新建redisconfig  注入 RedisMessageListenerContainer  Bean

@Configuration
public class RedisListenerConfig {
    @Bean
    RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {

        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        return container;
    }
}

 编写redis 监听类  继承KeyExpirationEventMessageListener

@Component
public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {

    public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
        super(listenerContainer);
    }
    @Override
    public void onMessage(Message message, byte[] pattern) {
        String expiredKey = message.toString();
        System.out.println("监听到过期的key为:"+expiredKey);
    }
}

  运行boot工程    使用redis 客户端 redis desktop manager添加一个key  设置过期时间

 

 延时两秒  在工程控制太看到输出

 

转载于:https://www.cnblogs.com/yongxiangliu123/p/11102843.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值