Redisson延迟队列稳定性测试

本文通过模拟生产者和消费者,使用Redisson3.16.4在Redis6.2.6环境中进行延迟队列测试。生产端发送10万条延迟消息,消费端进行轮询消费,结果显示在多次测试中未发现消息丢失现象,验证了Redisson延迟队列的稳定性。
摘要由CSDN通过智能技术生成
在一次探讨的过程中,听到有人使用Redisson延迟队列遇到了丢消息的问题。
于是打算自己做一个小测试,看看是否会有这种情况发生。

环境&版本

  • Redis 6.2.6(standalone)
  • Redisson 3.16.4(Netty 4.1.70)
  • JDK 17

测试

模拟2个生产端共发送10万延迟消息。
4个消费端轮流消费,检查是否能够完整拉取到10万个消息。
反复测试5次。
消息体
模拟一个简单的消息对象。
package cn.mrxionge.idemo.redisdq;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * 消息对象
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
class MsgDto {

    /**
     * 消息ID
     */
    private String id;

    /**
     * 消息标签
     */
    private String tag;

    /**
     * 消息内容
     */
    private String content;
}

消费端
模拟4个客户端不停地从队列中拉取并消费消息。
并且在每消费100个消息的时候,打印一次当前已消费的总数。
package cn.mrxionge.idemo.redisdq;

import org.redisson.Redisson;
import org.redisson.api.RBlockingQueue;
import org.redisson.api.RedissonClient;
import org.redisson.codec.JsonJacksonCodec;
import org.redisson.config.Config;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * 消费者
 */
public class RConsumer {

    public static void main(String[] args) throws InterruptedException {
        //配置redis连接
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379").setPassword("123456").setDatabase(0);
        //消息计数
        AtomicInteger msgCount = new AtomicInteger();
        for (int i = 0; i < 4; i++) {
            String name = "0" + i;
            new Thread(() -> {
                try {
                    //创建Redisson客户端
                    RedissonClient client = Redisson.create(config);
                    System.out.printf("消费者 %s 启动%n", name);
                    RBlockingQueue<MsgDto> queue = client.getBlockingQueue("delayed_msg_queue", JsonJacksonCodec.INSTANCE);
                    //循环消费消息 每消费100个打印一次实时消费总数
                    while (true) {
                        queue.take();
                        if (msgCount.incrementAndGet() % 100 == 0) {
                            System.out.printf("当前消费总数 %s%n", msgCount.get());
                        }
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

生产端
模拟2个客户端不停地向延迟队列中添加消息,每个客户端发5万个,共10万消息。
消息的延迟时间随机生成,延迟时间分别是5,10,15,20,25,30秒。
package cn.mrxionge.idemo.redisdq;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.IdUtil;
import org.redisson.Redisson;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RedissonClient;
import org.redisson.codec.JsonJacksonCodec;
import org.redisson.config.Config;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import static cn.hutool.core.util.RandomUtil.randomInt;
import static cn.hutool.core.util.RandomUtil.randomString;

/**
 * 生产者
 */
public class RProvider {

    public static void main(String[] args) throws InterruptedException {
        //配置redis连接
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379").setPassword("123456").setDatabase(0);
        //消息计数
        AtomicInteger msgCount = new AtomicInteger();
        CountDownLatch latch = new CountDownLatch(2);
        for (int i = 0; i < 2; i++) {
            String name = "0" + i;
            new Thread(() -> {
                int count = 0;
                //创建Redisson客户端
                RedissonClient client = Redisson.create(config);
                System.out.printf("生产者 %s 启动%n", name);
                RDelayedQueue<MsgDto> queue = client.getDelayedQueue(client.getQueue("delayed_msg_queue", JsonJacksonCodec.INSTANCE));
                //循环发送消息
                for (int j = 0; j < 50000; j++) {
                    MsgDto msgDto = new MsgDto(IdUtil.objectId(), "MSG_TAG_" + randomInt(1, 9), Base64.encode(randomString(10)));
                    queue.offer(msgDto, randomInt(1, 7) * 5L, TimeUnit.SECONDS);
                    count++;
                }
                System.out.printf("生产者 %s 发送 %s 条消息%n", name, count);
                msgCount.addAndGet(count);
                latch.countDown();
            }).start();
        }
        latch.await();
        System.out.printf("生产者共发送 %s 条消息%n", msgCount.get());
    }
}

结果

消费端控制台输出
消费者 03 启动
消费者 01 启动
消费者 00 启动
消费者 02 启动
当前消费总数 100
当前消费总数 200
当前消费总数 300
··· ···
··· ···
当前消费总数 99800
当前消费总数 99900
当前消费总数 100000
生产端控制台输出
生产者 00 启动
生产者 01 启动
生产者 01 发送 50000 条消息
生产者 00 发送 50000 条消息
生产者共发送 100000 条消息
反复测试5次,均没有发生丢失消息的情况。
如果在使用的过程中,担心会有消息丢失,我们可以在生产端和消费端都打印一下消息对象。这样在出问题的时候,我们可以根据日志来定位问题。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值