使⽤RedisTemplate批量存⼊数据,100万测试需要1分钟⽬录
参考⽂档
1.需求
将mysql数据库中的上百万数据存⼊redis中存⼊的格式为hashMap的形式
即,(hash路径,key, obj)其中的obj为map 封装⼀条记录信息
并且这些数据在⽤的时候可以取得到。
难点,普通通过循环hset的⽅式⽐较慢,⼀万条数据需要6秒左右,⼀百万需要10分钟左右
优化⽅案:redisTemplate的管道api executePipelined()
注意,仍需要将数据进⾏分段向redis中存⼊(不然被卡死),⽐如可以分段从数据库取然后分段存,
但是最好是⼀下⼦取出来,再分段存⼊,本案例是分段取分段存。
2.基本配置
<!--使⽤的是如下的依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
基本配置类(必须)
ample.studyspringboot.studyboot.utils.stuRedis;
import com.alibaba.fastjson.support.spring.GenericFastJsonRedisSerializer;
import org.springframework.beans.factory.annotation.Autowired;
import t.annotation.Bean;
import t.annotation.Configuration;
import org.RedisTemplate;
import org.dis.serializer.GenericJackson2JsonRedisSerializer;
import org.dis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
@SuppressWarnings("rawtypes")
@Autowired
private RedisTemplate redisTemplate;
/**
* 解决redis插⼊中⽂乱码
* @return
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
@Bean
public RedisTemplate redisTemplateInit() {
//设置序列化Key的实例化对象
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
//设置序列化Value的实例化对象
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setHashValueSerializer(new GenericFastJsonRedisSerializer());
return redisTemplate;
}
}
配置⽂件
#MYSQL链接
spring.datasource.sql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/redistest?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai spring.datasource.username=root
spring.datasource.password=lps123
# AOP
# spring.aop.auto=true
# 默认使⽤cglib动态代理
# 强制使⽤jdk代理(不要这样做)
#spring.aop.proxy-target-class=false
#mybatis配置
mybatis.mapper-locations = classpath:/mapper/*.xml
#pe-aliases-package=ity
#redis配置
#Redis服务器地址
#Redis服务器连接端⼝
#Redis数据库索引(默认为0)
#连接池最⼤连接数(使⽤负值表⽰没有限制)
#连接池最⼤阻塞等待时间(使⽤负值表⽰没有限制)
#连接池中的最⼤空闲连接
#连接池中的最⼩空闲连接
#连接超时时间(毫秒)
3.核⼼代码
ample.studyspringboot.studyboot.utils.stuRedis;
import com.alibaba.fastjson.JSON;
ample.studyspringboot.studyboot.dao.UserDao;
import org.apache.catalina.Pipeline;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.dis.RedisProperties;
import org.st.context.SpringBootTest;
import org.springframework.dao.DataAccessException;
import org.tion.RedisConnection;
import org.RedisCallback;
import org.RedisTemplate;
import st.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;springboot aop
import java.util.List;
import java.util.Map;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class Main {
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private UserDao userDao;
@Autowired RedisUtil redisUtil;
/**
* 读取缓存数据
*/
@Test
public void get() {
// ("908687_name_2726||908687_sex_2726||908687_hobby_2726908687_height_2726");
Map<String,Object> value = (Map<String,Object>)redisUtil.hget("nbs:hello:leaf","908687_name_2726||908687_sex_2726||908687_hobby_2726908687_heig System.out.JSONString(value));
System.out.("name"));
}
@Test
public void method2() {
CustomersToRedis("nbs:hello:leaf",0);
}
/**
* @Author lps
* @Description //TODO
* @Date 2020-07-25 15:21:44 星期六
* @Param [path, stepSize] pathhash值的路径,stepSize 步长多少数据查⼀次
* @return boolean
**/
public boolean CustomersToRedis(String path,int stepSize) {
long zero = System.currentTimeMillis();
//数据总量
int total = Count();
if(total==0){
return false;
}
stepSize=stepSize==0?100000:stepSize;
//分步
int step =(total%stepSize)==0?(total/stepSize):(total/stepSize+1);
long startTime;//开始时间
long selectTime;//查询花费时间
long endTime;//结束时间
long saveTime;//存⼊redis花费时间
long dis;
for(int j = 1;j<=step;j++){
System.out.println(">#第"+j+"次操作>#");
startTime= System.currentTimeMillis();
/
/查出stepSize条数据
List<Map<String,Object>> LimitUser((j-1)*stepSize,stepSize);
selectTime = System.currentTimeMillis();
System.out.println("查询花费时间:"+(selectTime-startTime)+"ms");
//将这些数据存⼊redis
handleSave(path, res);
saveTime = System.currentTimeMillis();
System.out.println("存⼊redis话费时间:"+(saveTime-selectTime)+"ms");
endTime= System.currentTimeMillis();
dis= endTime-startTime;
System.out.println("每⼗万条数据花费时间:"+dis+"ms");
System.out.println();//换⾏
}
long last = System.currentTimeMillis();
System.out.println("总共花费时间"+(last-zero)+"ms");
return true;
}
//RedisTemplate使⽤PipeLine
//使⽤管道存储
public void handleSave(String path,List<Map<String, Object>> maps) {
List resultList = utePipelined(new RedisCallback<String>() {
@Override
public String doInRedis(RedisConnection connection) throws DataAccessException {
connection.openPipeline();
String tempKey="";
for(Map<String,Object> map:maps){
("name")+"||"+("sex")+"||"+("hobby")+("height");
connection.Bytes(),Bytes(),ValueSerializer().serialize(map)); }
return null;
}
});
System.out.println("长度:"+resultList.size());
}
}
4.dao
ample.studyspringboot.studyboot.dao;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Map;
@Repository
public interface UserDao {
//分页查询
List<Map<String,Object>> getLimitUser(@Param("st") int st, @Param("ed") int ed);
/
/总条数
Integer getCount();
}
5.mapper/*.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-////DTD Mapper 3.0//EN" "/dtd/mybatis-3-mapper.dtd" > <mapper namespace="ample.studyspringboot.studyboot.dao.UserDao">
<select id="getLimitUser" resultType="java.util.Map">
select * from user limit #{st},#{ed};
</select>
<select id="getCount" resultType="java.lang.Integer">
select COUNT(*)cnt from user;
</select>
</mapper>
部分结果展⽰
redis存储结果
后台打印输出
可以看出查询花费由于是本机时间还不算长,如果是远程连接时间可能要长得多。
每次存10万,100万的数据⼤概需要56秒,如果不算链接查询的时间可能40秒就可以了。
6.数据表
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论