RedisTemplet批量插入数据

   

目录

一、通过Pipeline(管道)批量插入

二、使用multiSet批量插入

三、效率测试 

四、小结


        工作中常会遇到连续多次向Redis插入数据的场景,这时候要是使用for循环一条条的插入,效率低下不说,还显得low,不符合我们的B格,这时候就可以用到本文中所说的方法了

一、通过Pipeline(管道)批量插入

        使用redisTemplate.executePipelined重写RedisCallbackdoInRedis方法

RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
		redisTemplate.executePipelined(new RedisCallback<Object>() {
			@Override
			public Object doInRedis(RedisConnection redisConnection) throws DataAccessException {
				map.forEach((key,value) -> {
					redisConnection.set(serializer.serialize("pipeline"+key),serializer.serialize(String.valueOf(value)),
							Expiration.seconds(600), RedisStringCommands.SetOption.UPSERT);
				});
				return null;
			}
		},serializer);

         为什么在doInRedis方法中返回null呢?我们点进去executePipelined()方法的源码中可看到,若不为null就抛出异常

Object result = action.doInRedis(connection);
if (result != null) {
   throw new InvalidDataAccessApiUsageException("Callback cannot return a non-null value as             
   it gets overwritten by the pipeline");
}

二、使用multiSet批量插入

        效率最高,缺点是不能设置过期时间

redisTemplate.opsForValue().multiSet(map);

三、效率测试 

        本文使用三种方法插入五万条数据进行对比测试

@RestController
@RequestMapping("/testRedis")
@Slf4j
public class TestRedisController {

	@Resource
	private RedisTemplate<String ,Object> redisTemplate;

	private static Map<String, Object> map = new HashMap<>();

	@PostConstruct
	public void initMap(){
		for (int i = 0; i < 50000; i++) {
			map.put(i+"",i);
		}
		log.info("Map数据初始化完成,现有:{}",map.size());
	}

	@GetMapping("/testBatchInsert")
	@ApiOperation("批量插入")
	public ResultVO<Object> testBatchInsert(){
		// 常规循环插入
		long s2 = System.currentTimeMillis();
		map.forEach((key,value)->{
			redisTemplate.opsForValue().set("common"+key,value,10, TimeUnit.MINUTES);
		});
		long e2 = System.currentTimeMillis();
		log.info("常规循环插入耗时:{}",e2-s2);

		// 管道插入
		long start = System.currentTimeMillis();
		RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
		redisTemplate.executePipelined(new RedisCallback<Object>() {
			@Override
			public Object doInRedis(RedisConnection redisConnection) throws DataAccessException {
				map.forEach((key,value) -> {
					redisConnection.set(serializer.serialize("pipeline"+key),serializer.serialize(String.valueOf(value)),
							Expiration.seconds(600), RedisStringCommands.SetOption.UPSERT);
				});
				return null;
			}
		},serializer);
		long end = System.currentTimeMillis();
		log.info("管道批量插入耗时:{}",end-start);

		// 批量插入
		long s3 = System.currentTimeMillis();
		redisTemplate.opsForValue().multiSet(map);
		long e3 = System.currentTimeMillis();
		log.info("批量插入耗时:{}",e3-s3);

		return ResultUtils.success();
	}

}

        执行两次结果如下:

        

四、小结

        从测试结果可看出,使用multiSet()方式速度最快,管道次之,循环最慢;但multiSet最致命的就是无法设置过期时间,如果业务允许的话使用此方式最好;要根据实际的业务场景来选择使用哪种方式

        欢迎大家指正错误,转载请注明出处!

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值