Redis(3)---事务

Reids事务
1.在Redis中,也许存在多个客户端同时向Redis系统发送命令的并非的可能性,因此同一份数据可能被不同线程所操控,这样就出现了并发下的数据一致问题。
事物是一个被隔离的操作,事务中的方法都会被Redis按顺序执行,事务在执行过程中不会被其他客户端发生的命令所打断。例如,在Redis中开启事务是multi命令,执行事务是exec命令,开启到执行命令之间,Redis采取的是进入队列的形式,直到exec命令出现,才会一次性发送队列里的命令去执行,而在执行这些命令的时候其他客户端就不能再插入任何命令

2.事务的具体操作

//使用Redis事务
	@Test
	public void TestRedisTransaction()
	{
	  RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class);
	 /*edisTemplate直接调用opfor..来操作redis数据库,每执行一条命令是要重新拿一个连接,因此很耗资源,
	  让一个连接直接执行多条语句的方法就是使用SessionCallback*/
	 SessionCallback<Object> callback = new SessionCallback<Object>() {
	        @Override
	        public Object execute(RedisOperations operations) throws DataAccessException {
	        	String value1=null;
	            operations.multi();
	            operations.opsForValue().set("name", "qinyi");
	             value1 =  (String) operations.opsForValue().get("name");
	            operations.opsForValue().get("gender");
	            operations.opsForValue().get("age");
	            System.out.println("命令只是进入了队列,而没有被执行,所以此时value1应为空:"+value1);
	            operations.opsForValue().set("gender", "male");
	            operations.opsForValue().set("age", "19");
	            List<Object> list = operations.exec();
	            value1 =  (String) operations.opsForValue().get("name");
	            System.out.println("执行了exec()就不为空:"+value1);
	            System.out.println("list:"+list);
	            return list;
	        }
	    };
	    //执行Redis命令
	    List<Object> value = (List<Object>) redisTemplate.execute(callback);
	    System.out.println("excute方法的的返回值:"+value);
	   
	}

运行结果:
在这里插入图片描述
可以看到没有exec()命令之前get方法返回值一律为空,最后使用redisTemplate.execute执行我们再SessionCallBack的业务逻辑,否则将不会执行SessionCallBack中的内容;

事务回滚
如上代码

@Test
	public void TestRedisTransaction()
	{
	  RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class);
	 /*edisTemplate直接调用opfor..来操作redis数据库,每执行一条命令是要重新拿一个连接,因此很耗资源,
	  让一个连接直接执行多条语句的方法就是使用SessionCallback*/
	 SessionCallback<Object> callback = new SessionCallback<Object>() {
	        @Override
	        public Object execute(RedisOperations operations) throws DataAccessException {
	        	String value1=null;
	            operations.multi();
	            operations.opsForValue().set("name", "qinyi");
	             value1 =  (String) operations.opsForValue().get("name");
	            operations.opsForValue().get("gender");
	            operations.opsForValue().get("age");
	            System.out.println("命令只是进入了队列,而没有被执行,所以此时value1应为空:"+value1);
	            operations.opsForValue().set("gender", "male");
	            operations.opsForValue().set("age", "19");
	            **operations.discard();  //事务回滚 当事务回滚后还进行exec命令,会报异常**
	            List<Object> list = operations.exec();
	            value1 =  (String) operations.opsForValue().get("name");
	            System.out.println("执行了exec()就不为空:"+value1);
	            System.out.println("list:"+list);
	            return list;
	        }
	    };
	    //执行Redis命令
	    List<Object> value = (List<Object>) redisTemplate.execute(callback);
	    System.out.println("excute方法的的返回值:"+value);
	   
	}

对于Redis而言,其回滚能力也和数据库不太一样。需要特别注意两个地方:
1.Redis事务遇到命令格式正确而数据类型不符合时
例如:

@Test
		public void TestRedisRollback() {
			  RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class);
			SessionCallback<Object> callback = new SessionCallback<Object>() {
		        @Override
		        public Object execute(RedisOperations operations) throws DataAccessException {
		        	operations.multi();
		        	//这里我设置了String类型的字符串
		        	operations.opsForValue().set("number","asd1");
		        	operations.opsForValue().set("哈哈","sdsd");
		        	//对字符串执行+1操作
		        	operations.opsForValue().increment("number", 1);
		            return operations.exec();
		        }
		    };
		    System.out.println(redisTemplate.execute(callback));			
		}

在这里插入图片描述
在这里插入图片描述
虽然控制台抛出了异常,但是其之前之后的命令依然set了进去,没有回滚。
2.Redis对于命令格式错误却是另外一种情况
在这里插入图片描述如图我们开启缓存 同样像执行增加操作,但是故意将命令输入错误 然后再提交,而出现这种命令格式错误,redis前后都直接回滚了,得到的值都为空

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值