您的位置:首页 > 数据库 > Redis

RedisTemplate实现事物问题剖析和解决

2017-05-22 14:10 225 查看

一、问题描述

Redis为单进程单线程模式,采用队列模式将并发访问变成串行访问,Redis对事物支持不会很复杂,当一个客服端连接Redis服务时,发出了MULTI命令时,这个连接会进入事物,在执行MULTI命令之后,执行所有的命令都不会执行,会先放到一个队列中,会提示正在Query,当最后执行EXEC命令之后,Redis会按照之前的进入队列的顺序,执行命令。

Spring Data Redis 是对JRedis的客服端进行很好的封装, spring Data Redis的RedisTemplate提供了MULTI、EXEC命令进行封装,但RedisTemplate先执行调用MULTI方法,然后在执行其它的命令,最后执行EXEC方法时,会出现报错:Caused by:Redis.clents.jedis.exceptions.JedisDataException:ERR EXEC without MULTI问题。

二、原因分析

Redis为单进程单线程模式,采用队列模式将并发访问变成串行访问,我们需要重新添加数据,对原先的数据进行删除,在多个线程情况下数据会丢失,所以我们需要事务完成相应的效果。

Spring Data Redis的RedisTemplate提供了MULTI、EXEC命令进行封装,远看可以解决问题时,代码实现:

[java] view plain copy

stringRedisTemplate.multi();

stringRedisTemplate.delete("test");

stringRedisTemplate.opsForValue().set("test","2");

stringRedisTemplate.exec();

结果保 错误:



我们查询multi、delete等源代码,发现会执行RedisTemplate类中execute()方法进行跟踪发现 RedisCallback中doInRedis获取的RedisConnection每次都是新的,所以才导致该问题。

分析Redis源代码:

我们查看multi实现





跟踪发现RedisConnection conn每次都是新的,导致出现那个错误

三、解决方案

只能自己实现RedisCallBack底层,采用RedisTemplate的SesionCallback来完成在同一个Connection中,完成多个操作的方法:

SessionCallback<Object> sessionCallback=new SessionCallback<Object>(){

@Override

public Object execute(RedisOperations operations) throws DataAccessException{

operations.multi();

operations.delete("test");

operations.opsForValue.set("test","2");

Object val=operations.exec();

return val;

}

}

StringRedisTemplate.execute(sessionCallback);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐