java中redis的watch與Transaction功能使用

以前一直了解redis中的事務機制,知道事務並無真正的回滾,只是會中斷,中斷後的將不會執行,中斷前的會生效。java

使用是若是遇到但願保持原子性的更改,除了自增的簡單操做,redis作的並非很完善。redis

在項目中遇到了一個使用redis並但願原子性更改值的須要,記錄一下。code

/**
	* @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.在事務提交以後返回的結果對象分爲幾種狀況ip

    事務提交前,watch的key發生改變,返回的List對象並非null,而是一個初始化後的空對象(size==0)get

    事務提交前,watch的key沒有改變,事務提交成功,返回的List對象中有一個"OK"的String對象。io

相關文章
相關標籤/搜索