商务合作

解决Redisson延时队列严重问题

延时队列原理我在这篇文章讲了

罗政:Redisson 延时队列 原理 详解40 赞同 · 19 评论文章


十分建议先把原理看了


我们一个项目是做消息推送的, 分钟量达到了几百万需求是要设置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延时队列定制开发源码​githubs.xyz/sale/sale.html?id=1


由于代码有知识产权,能解决实际问题,所以见谅~~~~~

代码有问题可以及时联系我,qq:657455400 wx:hadluo