springboot框架redis开启管道批量写入数据

发布于:2025-07-08 ⋅ 阅读:(15) ⋅ 点赞:(0)

1. 整体描述

在使用spring框架做业务开发时,很多时候使用redis做缓存,缓存写入时通常会有大量数据写入的场景,如果按照正常写入方式进行操作,性能和效率会很慢,这里推荐使用管道pipeline方式写入,能显著提升性能。

2. 前期准备

2.1 redis

电脑需要安装redis,或者有redis环境。

2.2 springboot工程

需要一个springboot工程,用于测试功能,如果没有可以看我之前写的这个文章:使用idea创建springboot单体项目

3. 具体步骤

3.1 pom引用

在pom增加redis相关引用:

        <!-- redis 缓存操作 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!-- lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

3.2 增加redis参数

在配置文件yml中增加redis相关参数:

server:
  port: 9527
spring:
  # Redis配置
  data:
    redis:
      database: 1
      host: 127.0.0.1
      port: 6379

3.3 增加redis的配置类

package com.thcb.springboottestdemo.framework.config;

import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.text.SimpleDateFormat;
import java.util.TimeZone;

@Configuration
public class RedisConfig {

    @Value("${spring.data.redis.host}")
    private String redisHost;

    @Value("${spring.data.redis.port}")
    private int redisPort;

    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
        config.setHostName(redisHost);
        config.setPort(redisPort);
        return new LettuceConnectionFactory(config);
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory());

        // 自定义 ObjectMapper
        ObjectMapper objectMapper = new ObjectMapper();
        // 设置日期格式
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        // 设置时区(可选,根据业务需求)
        objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));
        // 设置 key 和 value 的序列化器
        objectMapper.activateDefaultTyping(
                LaissezFaireSubTypeValidator.instance,
                ObjectMapper.DefaultTyping.NON_FINAL,
                JsonTypeInfo.As.PROPERTY
        );
        // 使用GenericJackson2JsonRedisSerializer允许null
        template.setDefaultSerializer(new GenericJackson2JsonRedisSerializer());
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer(objectMapper));
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer(objectMapper));

        return template;
    }


}

3.4 创建redis工具类

其中,批量缓存对象方法就是使用管道写入的。

package com.thcb.springboottestdemo.framework.redis;

import com.thcb.springboottestdemo.project.redis.vo.RedisKeyValueVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * spring redis 工具类
 *
 * @author thcb
 * @date 2025-07-04
 **/
@Component
public class RedisCache {

    @Autowired
    public RedisTemplate<String, Object> redisTemplate;

    /**
     * 缓存基本的对象,Integer、String、实体类等
     *
     * @param key   缓存的键值
     * @param value 缓存的值
     */
    public void setCacheObject(String key, Object value) {
        redisTemplate.opsForValue().set(key, value);
    }


    /**
     * 缓存基本的对象,Integer、String、实体类等
     *
     * @param key      缓存的键值
     * @param value    缓存的值
     * @param timeout  时间
     * @param timeUnit 时间颗粒度
     */
    public void setCacheObject(String key, Object value, Integer timeout, TimeUnit timeUnit) {
        redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
    }

    /**
     * 批量缓存对象
     *
     * @param list     缓存的键值
     * @param timeout  时间
     * @param timeUnit 时间颗粒度
     */
    public void setCacheObject(List<RedisKeyValueVO> list, Integer timeout, TimeUnit timeUnit) {
        redisTemplate.executePipelined(new SessionCallback<Object>() {
            @Override
            public <K, V> Object execute(RedisOperations<K, V> operations) throws DataAccessException {
                for (RedisKeyValueVO vo : list) {
                    setCacheObject(vo.getKey(), vo.getValue(), timeout, timeUnit);
                }
                return null;
            }
        });
    }

    /**
     * 获得缓存的基本对象
     *
     * @param key 缓存键值
     * @return 缓存键值对应的数据
     */
    public Object getCacheObject(String key) {
        return redisTemplate.opsForValue().get(key);
    }


    /**
     * 删除单个对象
     *
     * @param key 缓存键值
     */
    public void deleteObject(String key) {
        redisTemplate.delete(key);
    }

}

3.5 创建VO类

package com.thcb.springboottestdemo.project.redis.vo;

import lombok.Data;

@Data
public class RedisKeyValueVO {
    public String key;
    public String value;

    public RedisKeyValueVO(String key, String value) {
        this.key = key;
        this.value = value;
    }
}

3.6 创建service类

package com.thcb.springboottestdemo.project.redis.service;

/**
 * Redis 业务接口
 *
 * @author thcb
 * @date 2025-07-04
 */
public interface IRedisService {

    /**
     * 处理数据
     */
    public void processData();

}

3.7 创建impl类

package com.thcb.springboottestdemo.project.redis.service.impl;

import com.thcb.springboottestdemo.framework.redis.RedisCache;
import com.thcb.springboottestdemo.project.redis.service.IRedisService;
import com.thcb.springboottestdemo.project.redis.vo.RedisKeyValueVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * redis Service业务层处理
 *
 * @author thcb
 * @date 2025-07-04
 */
@Service
public class IRedisServiceImpl implements IRedisService {

    @Autowired
    private RedisCache redisCache;

    /**
     * 处理数据
     */
    @Override
    public void processData() {
        // 构造数据
        List<RedisKeyValueVO> list = new ArrayList<>();
        list.add(new RedisKeyValueVO("redis:demo:key1", "value1"));
        list.add(new RedisKeyValueVO("redis:demo:key2", "value2"));
        list.add(new RedisKeyValueVO("redis:demo:key3", "value3"));
        // 缓存数据
        redisCache.setCacheObject(list, 60 * 60 * 24 * 7, TimeUnit.SECONDS);
    }
}

3.8 controller类

package com.thcb.springboottestdemo.test.controller;

import com.thcb.springboottestdemo.project.redis.service.IRedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/test")
public class TestController {

    @Autowired
    private IRedisService redisService;

    @PostMapping("/post")
    public String post() {
        return "post success";
    }

    @GetMapping("/get")
    public String get() {
        return "get success";
    }

    @GetMapping("/processRedisData")
    public String processRedisData() {
        redisService.processData();
        return "pressureTest success";
    }

}

3.9 调用测试

调用接口测试下
接口调用

3.10 redis查看

查看redis结果,已经成功存入。
redis

4. 总结

使用pipeline写入效率会高很多,在生产环境写入大量redis数据时,推荐使用管道方式写入,配合xxl-job等定时任务处理。


网站公告

今日签到

点亮在社区的每一天
去签到