springboot框架redis开启管道批量写入数据
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结果,已经成功存入。
4. 总结
使用pipeline写入效率会高很多,在生产环境写入大量redis数据时,推荐使用管道方式写入,配合xxl-job等定时任务处理。