Springboot 批量增加redis中的数据,并批量设置过期时间

1. 背景

一个功能需要一次性解析大量数据放到 Redis 中缓存,并且每个 key 都需要设置过期时间,但是 Redis 本身命令不支持批量设置过期时间,RedisTemplate 中也没有相关的方法。

2. 实现方式

1. RedisTemplate 使用 redisTemplate.opsForValue().multiSet() 来实现批量插入数据
2. RedisTemplate使用PipeLine管道命令来批量修改过期时间

3. 代码

bash 复制代码
package com.insupro.flexibleServerJ.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StopWatch;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author luoqifeng
 */
@Slf4j
@RestController
@RequestMapping("/api")
public class RedisDemo002 {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @RequestMapping("testRedisMultiSet")
    public Object testRedisMultiSet() {
        Map<String, String> keysAndValues = new HashMap<>();
        // 模拟数据
        for (int i=0; i < 100; i++){
            String redisKey = "testKey_"+i;
            String value = "testValue_"+i;
            keysAndValues.put(redisKey, value);
        }

        if (!keysAndValues.isEmpty()){
            StopWatch stopWatch = new StopWatch();
            stopWatch.start("正常遍历上传计时");

            for (String key: keysAndValues.keySet()){
                redisTemplate.opsForValue().set(key, keysAndValues.get(key), 20, TimeUnit.SECONDS);
            }
            stopWatch.stop();

            // 以下是批量上传方式
            stopWatch.start("批量上传redis计时");
            redisTemplate.opsForValue().multiSet(keysAndValues);
            // 设置过期值
            stopWatch.stop();
            stopWatch.start("批量设置过期时间");

            redisTemplate.executePipelined((RedisCallback<Object>) connection -> {
                keysAndValues.forEach((key, vaul) -> {
                    connection.expire(key.getBytes(), 20);
                });
                return null;
            });
            stopWatch.stop();
            log.info("执行耗时:{}", stopWatch.prettyPrint());
        }
        return  null;
    }
}

执行代码结果:

可以看到,普通遍历上传因为每次都需要发起一次请求,造成多次请求消耗,从而占用大量时间,而使用批量上传可以通过PipeLine管道命令来设置过期时间,只会有两次请求,时间上大幅度提升。

疑问:为什么不直接使用管道上传并设置过期时间呢?

回答: 当然可以,我只是做个演示,具体实现需要根据业务需求做相应的操作。

例如:通过管道实现简单限流思想逻辑

bash 复制代码
    //限流器
    public void currentLimiter(){
        List<Object> objects = redisTemplate.executePipelined(new RedisCallback<Long>() {
            @Override
            public Long doInRedis(RedisConnection connection) throws DataAccessException {
                connection.openPipeline();
                //key
                String key = "userId:mucontroller:save";
                //当前时间
                Long time = System.currentTimeMillis();
                //限定1min中内的请求
                Long period = 1L;
                //请求记录
                connection.zSetCommands().zAdd(key.getBytes(), time, key.getBytes());
                //删除1min之外的请求
                connection.zSetCommands().zRemRangeByScore(key.getBytes(), 0.0, Double.valueOf(time - period * 1000));
                //统计1min内的记录次数
                Long size = connection.zSetCommands().zCard(key.getBytes());
                //设置过期时间
                connection.expire(key.getBytes(), period);
                if(size > 3){
                    return 0L;
                } else {
                    return 1L;
                }
            }
        });
    }

end

以上都是实例,需要根据自行业务逻辑进行修改封装,以确保程序的健壮性

相关推荐
纪元A梦1 分钟前
Redis最佳实践——性能优化技巧之监控与告警详解
数据库·redis·性能优化
啊松同学2 分钟前
【Mybatis】MyBatisPlus的saveBatch真的是批量插入吗?深度解析与性能优化
java·后端·性能优化·mybatis
阿里小阿希25 分钟前
解决 Spring Boot + MyBatis 项目迁移到 PostgreSQL 后的数据类型不匹配问题
spring boot·postgresql·mybatis
uhakadotcom30 分钟前
Lovable:用AI轻松打造完整应用,零基础也能快速开发
后端·面试·架构
小希爸爸32 分钟前
4、中医基础入门和养生
前端·后端
码起来呗37 分钟前
基于SpringBoot的高校学习讲座预约系统-项目分享
spring boot·后端·学习
Asthenia041244 分钟前
Reactor 模型详解:从单线程到多线程及其在 Netty 和 Redis 中的应用
后端
广西千灵通网络科技有限公司1 小时前
基于 springboot+vue+elementui 的办公自动化系统设计(
vue.js·spring boot·elementui
听雨·眠1 小时前
go语言中defer使用指南
开发语言·后端·golang
bing_1582 小时前
在 Spring Boot 项目中如何使用索引来优化 SQL 查询?
spring boot·sql·索引优化