Redis管道

257 阅读1分钟

技术对比

普通redis客户端和服务器交互模式 image.png

Pipeline请求模型

image.png

官方测试数据对比

image.png

测试案例

导入工具类

工具类代码看我这一篇:Springboot集成Redis - 掘金 (juejin.cn)

相关代码

//耗时6151
@Test
public  void testPiple1(){
    long start =System.currentTimeMillis();
    for (int i = 0; i <10000 ; i++) {
        Task task = new Task();
        task.setTaskType(1001);
        task.setPriority(1);
        task.setExecuteTime(new Date().getTime());
        cacheService.lLeftPush("1001_1", JSON.toJSONString(task));
    }
    System.out.println("耗时"+(System.currentTimeMillis()- start));
}


// 耗时1788
@Test
public void testPiple2(){
    long start  = System.currentTimeMillis();
    //使用管道技术
    List<Object> objectList = cacheService.getstringRedisTemplate().executePipelined(new RedisCallback<Object>() {
        @Nullable
        @Override
        public Object doInRedis(RedisConnection redisConnection) throws DataAccessException {
            for (int i = 0; i <10000 ; i++) {
                Task task = new Task();
                task.setTaskType(1001);
                task.setPriority(1);
                task.setExecuteTime(new Date().getTime());
                redisConnection.lPush("1001_1".getBytes(), JSON.toJSONString(task).getBytes());
            }
            return null;
        }
    });
    System.out.println("使用管道技术执行10000次自增操作共耗时:"+(System.currentTimeMillis()-start)+"毫秒");
}

实际案例

每一分钟执行一次该方法,如果"未来任务"执行时间到了,会将其转换为"现在任务"

(主要看倒数最后几行的refreshWithPipeline方法)

/**
 * 未来数据定时刷新
 */
@Scheduled(cron = "0 */1 * * * ?")
public void refresh() {

    String token = cacheService.tryLock("FUTRUE_TASK_SYNC", 1000 * 30);

    if(StringUtils.isNotBlank(token)){
        log.info("未来数据定时刷新---定时任务");

        //获取所有未来数据的集合key
        Set<String> futureKeys = cacheService.scan(ScheduleConstants.FUTURE + "*");
        for (String futureKey : futureKeys) {
            //future_100_50

            //获取当前数据的key  topic
            String topicKey = ScheduleConstants.TOPIC + futureKey.split(ScheduleConstants.FUTURE)[1];

            //按照key和分值查询符合条件的数据
            Set<String> tasks = cacheService.zRangeByScore(futureKey, 0, System.currentTimeMillis());

            //同步数据
            if (!tasks.isEmpty()) {
                cacheService.refreshWithPipeline(futureKey, topicKey, tasks);
                log.info("成功的将" + futureKey + "刷新到了" + topicKey);
            }
        }
    }
}

refreshWithPipeline 方法:将传入的未来任务集合批量刷新为现在任务

public List<Object> refreshWithPipeline(String future_key,String topic_key,Collection<String> values){

    List<Object> objects = stringRedisTemplate.executePipelined(new RedisCallback<Object>() {
        @Nullable
        @Override
        public Object doInRedis(RedisConnection redisConnection) throws DataAccessException {
            StringRedisConnection stringRedisConnection = (StringRedisConnection)redisConnection;
            String[] strings = values.toArray(new String[values.size()]);
            stringRedisConnection.rPush(topic_key,strings);
            stringRedisConnection.zRem(future_key,strings);
            return null;
        }
    });
    return objects;
}