Spring Redis 事务Multi Exec Watch

 

今天在测试spring Redis的时候出现这么个:

org.springframework.dao.InvalidDataAccessApiUsageException: ERR EXEC without MULTI; nested exception is redis.clients.jedis.exceptions.JedisDataException: ERR EXEC without MULTI 

另外还报: java.lang.NullPointerException

先记录下, http://stackoverflow.com/questions/11148383/how-to-implement-redis-multi-exec-by-using-spring-data-redis All Spring Configuration is written properly. Non-Multi-Exec Redis operations work perfectly. @Autowired @Qualifier("stringRedisTemplate") StringRedisTemplate template; void test(){   template.multi();   template.boundValueOps("somevkey").increment(1);   template.boundZSetOps("somezkey").add("zvalue", timestamp);   template.exec(); } After running above code through Junit Test, Exceptions are thrown. Unknown exception; nested exception is org.springframework.data.redis.RedisSystemException: Unknown jedis exception; nested exception is java.lang.NullPointerException The reason for the exception is probably that the Spring template implementation does not reuse the same connection for .multi() and .exec(). You can try to use execute() via a callback: private RedisTemplate template = ...; template.execute( new RedisCallback() { @Override public Object doInRedis(RedisConnection connection) throws DataAccessException { connection.multi(); //do whatever you need, like deleting and repopulating some keys connection.expire(CHANNEL_KEY.getBytes(), EXPIRE_SECS); connection.exec(); return null; });

先记录下,希望明天去公司能搞定 http://forum.springsource.org/archive/index.php/t-125387.html Hello! I am getting very many exceptions and strange results using redisTemplate and it's callbacks. Problems we spotted in:

Multi-Discard using RedisCallback Multi-Exec using RedisCallback Watch-Multi-Exec using RedisCallback Multi-Exec in pipelined RedisCallback Watch-Multi-Unwatch-Exec using RedisCallback Also two bugs we spotted and added to JIRA: DATAREDIS-87, DATAREDIS-88 For some reason I was not able to attach file with code. Will email it on demand. Sample:

@Test public void testMultiDiscard1() throws Exception { redisTemplate.execute(new RedisCallback<Object>() { @Override public Object doInRedis(RedisConnection connection) throws DataAccessException { connection.set("a".getBytes(), "b".getBytes()); assertEquals(1, redisTemplate.keys("a").size()); connection.multi(); assertEquals(1, redisTemplate.keys("a").size()); connection.set("a".getBytes(), "bbb".getBytes()); connection.append("a".getBytes(), "ccc".getBytes()); connection.hSet("a1".getBytes(), "field1".getBytes(), "1000".getBytes()); connection.hIncrBy("a1".getBytes(), "field1".getBytes(), 10); Map<byte[], byte[]> args = new HashMap<byte[], byte[]>(3); args.put("field2".getBytes(), "valueX".getBytes()); args.put("field3".getBytes(), "valueY".getBytes()); args.put("field4".getBytes(), "000".getBytes()); connection.hMSet("a2".getBytes(), args); connection.append("a3".getBytes(), "bunny".getBytes()); assertEquals(1, redisTemplate.keys("a").size()); assertTrue(redisTemplate.keys("a1").isEmpty()); connection.discard(); return null; } }, true); assertNotNull(redisTemplate.opsForValue().get("a")); assertTrue(redisTemplate.opsForHash().values("a1").isEmpty()); }

I was working on a redis mock to be able to test without real redis. When run the tests on real one quite a big number of them failed, but shouldn't (as for me). Maybe I'm doing smth wrong? Thanks in advance!

Building Applications with Spring Data Redis http://www.packtpub.com/article/building-applications-spring-data-redis

 

 
 
 
 
处理、分离和浓缩等操作,以便更准确地进行检测。 四、结论 随着科技是的,Spring Boot的`@Transactional`注解可以支持Redis事务。但需要注意的是,Redis事务的不断进步,新型传感器及其相关检测技术不断涌现,它们具有小型模型与关系型数据库的事务模型有很大的区别。Redis事务不是像关系型数据库一样的ACID事务,而是一种乐观锁事务模型,也被称为WATCH/MULTI化、高灵敏度、快速响应和可重复使用等特点,被广泛应用于医疗、/EXEC事务模型。 在使用`@Transactional`注解时,需要在方法上添加该注解,并且在方法工业、环境等领域。未来,随部使用`multi()`方法开启事使用`exec()`方法提交事务,或者使用`discard()`方法回滚事务。具体示例代码如下: ```java @Service public class RedisService { @Autowired private RedisTemplate<String, Object> redisTemplate; @Transactional public void updateRedisData() { // 开启事务 redisTemplate.multi(); try { // 执行一系列Redis操作 redisTemplate.opsForValue().set("key1", "value1"); redisTemplate.opsForValue().increment("key2", 1); // 提交事务 redisTemplate.exec(); } catch (Exception e) { // 回滚事务 redisTemplate.discard(); } } } ``` 需要注意的是,Redis事务并不支持回滚到保存点,只能回滚到事务开始前的状态。因此,在使用Redis事务时,需要特别小心,确保每个操作都能正确执行。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值