springboot redis并发实现记录
前言(说一下这过程中我踩的坑)
redis并发写入防止数据在写入过程中已经被修改再写入后数据不对的处理方法如下
那么我按照上面的流程准备开干,我使用的是springboot封装的StringRedisTemplate来操作redis,刚好我看到这里面需要的方法都有,于是我就先调用watch监控、然后get到数据、修改、multi开启事务、set写入、exec提交,结果提交这里就报了异常,Redis.clents.jedis.exceptions.JedisDataException:ERR EXEC without MULTI。查询之后发现RedisConnection conn每次都是新的,导致出现那个错误。也就是说提交的redis连接和开始的不是同一个这就很坑了、详情见RedisTemplate实现事物问题剖析和解决,解决方法就是重写SessionCallback的execute方法就可以解决问题。
实现
//监控的key
String [] s = {"test1","test2"};
final boolean[] flag = {true};
while (flag[0]) { //如果失败则重试
Object o = stringRedisTemplate.execute(new SessionCallback<Object>() {
@Override
public Object execute(RedisOperations redisOperations) throws DataAccessException {
List<Object> result = null;
redisOperations.watch(Arrays.asList(s));
Integer test1 = redisClient.get("test1",Integer.class);
Integer test2 = redisClient.get("test2",Integer.class);
if(test1==null || test2==null) {
flag[0] = false;
return null;
}
redisOperations.multi();
redisOperations.opsForValue().set("test1",test1+1+"");
redisOperations.opsForValue().set("test2",test2+1+"");
//这里会返回一个boolean数组 记录提交的结果,这里由于上面开启了监控,成功就是全部成功,失败全部失败全失败会返回一个空数组
result = redisOperations.exec();
redisOperations.unwatch();
//result 不为null和空数组则成功
if(result != null && result.size()!=0) flag[0] = false;
return result;
}
});
}