@RunWith(SpringRunner.class)
@SpringBootTest(classes = AdminApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@EnableConfigurationProperties(RedisInfo.class)
public class DelayTaskTest {

    @Autowired
    private ZSetRedisTemplate zSetRedisTemplate;

    @Test
    public void test() {
        this.productionDelayMessage();
        this.consumerDelayMessage();
    }

    //生产者,生成5个订单放进去
    public void productionDelayMessage() {
        for (int i = 0; i < 5; i++) {
            //延迟10秒
            Calendar cal1 = Calendar.getInstance();
            cal1.add(Calendar.SECOND, 10);
            int second3later = (int) (cal1.getTimeInMillis() / 1000);
            zSetRedisTemplate.zadd("OrderId", second3later, "OID0000001" + i);
            System.out.println(System.currentTimeMillis() + "ms:redis生成了一个订单任务:订单ID为" + "OID0000001" + i);

        }

    }

    //消费者,取订单
    public void consumerDelayMessage() {
        while (true) {
            Set<Tuple> items = zSetRedisTemplate.zrangeWithScores("OrderId", 0, 0);

            if (CollectionUtils.isEmpty(items)) {
                System.out.println("当前没有等待的任务");
                try {
                    Thread.sleep(500);
                } catch (InterruptedException ignored) {

                }
                continue;
            }

            int score = (int) ((Tuple) items.toArray()[0]).getScore();
            Calendar cal = Calendar.getInstance();
            int nowSecond = (int) (cal.getTimeInMillis() / 1000);

            System.out.println("当前时间:" + DateUtil.formatCurrentDateTime());
            if (nowSecond >= score) {
                String orderId = ((Tuple) items.toArray()[0]).getElement();
                Boolean isRem = zSetRedisTemplate.zrem("OrderId", orderId);
                if (isRem) {
                    System.out.println(System.currentTimeMillis() + "ms:redis消费了一个任务:消费的订单OrderId为" + orderId);
                }
            }
        }
    }


}

优缺点:

  • 优点:由于使用 Redis 作为消息通道,消息都存储在 Redis 中。如果发送程序或者任务处理程序挂了,重启之后,还有重新处理数据的可能性;做集群扩展相当方便;时间准确度高。

  • 缺点:需要额外进行 Redis 维护。

这种实现方法,缺点是最少的,故记录下。