@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 维护。
这种实现方法,缺点是最少的,故记录下。