java中redis的watch与Transaction功能使用

之前一直了解redis中的事务机制,知道事务并没有真正的回滚,只是会中断,中断后的将不会执行,中断前的会生效。

使用是如果遇到希望保持原子性的更改,除了自增的简单操作,redis做的并不是很完善。

在项目中遇到了一个使用redis并希望原子性更改值的需要,记录一下。

/**
	* @Description: value greater than get value then set value 设置key值,如果传的value比redis中的value大则设置传入的value
	* @param key 需要设置的key
	* @param value 需要设置的value
	* @return: boolean
	* @Author: wangtongxing
	* @Date: 2019/1/11
	*/
	public static boolean vGtGetSet(String key, long value) {
		String s = null;
		Jedis jedis = null;
		try {
			jedis = JedisPoolUtils.getJedis();
			List<Object> exec = null;
			int i=0;
			while ((exec == null || exec.size()==0 || !"OK".equals(exec.get(0))) && i<5){
				jedis.watch(key);
				String getS = jedis.get(key);
				long get = 0;
				if (StringUtils.isNotEmpty(getS)){
					try {
						get = Long.parseLong(getS);
					}catch (Exception e){
						e.printStackTrace();
					}
				}
				if (value>get){
					Transaction transaction = jedis.multi();//返回一个事务控制对象
					transaction.set(key, Long.toString(value));//预先在事务对象中装入要执行的操作
					transaction.expire(key, CACHE_6_MONTHS);
					exec = transaction.exec();//执行
				}else {
					jedis.unwatch();
					return true;
				}
				i++;
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JedisPoolUtils.returnRes(jedis);
		}
		return false;
	}

使用中需要注意的几个点:

1.在不成功的情况下,一般需要重试几次,在重试的过程中每次循环都需要重新watch操作,因为每次事务提交之后,watch操作都会失效。

2.在事务提交之后返回的结果对象分为几种情况

    事务提交前,watch的key发生改变,返回的List对象并不是null,而是一个初始化后的空对象(size==0)

    事务提交前,watch的key没有改变,事务提交成功,返回的List对象中有一个"OK"的String对象。

转载于:https://my.oschina.net/u/1760932/blog/3001237

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值