延时队列原理我在这篇文章讲了
Redisson 延时队列 原理 详解 - 知乎
十分建议先把原理看了
我们一个项目是做消息推送的, 分钟量达到了几百万。需求是要设置5秒以上的延时推消息。
当初我想了几个方案:
-
定时器轮询数据库
-
mq做延时推送
-
redisson做延时推送
定时器轮询数据库 这种方案直接pass, 需求是要5秒的延时推送,你不可能弄个秒级的定时器去扫库,这样迟早会出问题。
mq做延时推送,当初也测试过,如果堆积了。消息绝达不打5秒的延时。
redisson 刚好,由于是采用了redis做延时队列,性能超高,而且还能持久化,到线上推送效果也表现极好,没出过问题(前提是我二次定制开发过)。
下面是我开发环境测试结果
当我设置了14511条数据到redisson延时队列时,取出来的时间在本身的延时时间上还延时了198636多毫秒。而且延时时间随着数据增加而增加。
我想这不是完蛋了吗。我想这完全没有发挥redis的优势。于是我基于redisson 进行了二次开发(集群思想)。
下面是我优化后的测试结果:
10万多条数据,真实延时时间最大33399毫秒,已经表现很好了,毕竟我开发环境redis特别垃圾。
如何使用定制后的redisson 延时队列
1. 引入maven依赖
<dependency>
<groupId>com.hadluo.queue</groupId>
<artifactId>redisson-delay-queue</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
2. 启动配置
@SpringBootApplication
@EnableRedissonFastDelayQueue(partition = 3, poll = 2) // 开启延时队列
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
@EnableRedissonFastDelayQueue 注解配置:
-
partition : 延时队列的 分区数 (延时有瓶颈时 可适当调大次数,但是会耗redis cpu 性能)。 可自行测试调整。
-
poll: 拉取队列数据的线程数(业务执行过慢可以稍微调大)。
加上 EnableRedissonFastDelayQueue 注解就会自动读取redis配置进行加载延时队列。 redis 地址配置:
# 单机 redis
spring.redis.node = 127.0.0.1:6379
# 带密码的redis
spring.redis.password = xxx
# 集群 redis
spring.redis.cluster.nodes = 127.0.0.1:6379
到此配置就完成了, 非常简单。那么我们业务怎么用?
比如 有一个 延时消息要处理 ,首先新建延时队列的回调监听类:
@RedissonFastDelayQueueClient
public class OnReceiveMsg {
@DelayTrigger
public void accept(String body) {
System.err.println("收到延时队列数据");
}
}
加上 @RedissonFastDelayQueueClient 注解后,就代表是 延时队列有数据后回调的类,里面的方法配置了 @DelayTrigger注解 就代表回调执行的方法。
发送数据:
@RestController
public class OrderController {
@GetMapping("/set")
public void set() {
FastDelayQueueContext.send(OnReceiveMsg.class, "我是发送的数据", 2000);
}
}
通过FastDelayQueueContext静态方法 就可往延时队列发送数据。
参数解释:
-
OnReceiveMsg.class : 接收延时回调的执行客户端,也就是配置了@RedissonFastDelayQueueClient注解。
-
发送的数据对象,可以是自定义的。
-
延时的秒数。
问题注意
使用要注意两个问题:
-
当量很大的时候,如果设置的 partition ,poll 在10 左右,由于极致压榨了cpu性能,保证延时队列不延时,CPU能打到 50% 。所以尽量将延时队列部署到单独机器, 或者降低 partition ,poll 的大小,最好设置在5以下。
-
延时队列 RedissonFastDelayQueueClient 的 回调 处理耗时不能太长, 如果量很大,可能会导致 poll 线程池堆积。
代码获取
由于开发不易,可以在这个上面下载我定制后的源码,不用担心代码性能,这个是我们线上已经用了一年多了。 你也可以压测下。
Redisson延时队列定制开发源码 在github上
https://github.com/HadLuo/sourcecode_download.git