redis的hmset乐观锁的实现
生活随笔
收集整理的這篇文章主要介紹了
redis的hmset乐观锁的实现
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
1.lua腳本(集成實(shí)現(xiàn)了樂觀鎖,hmset ,expire等)
local key=KEYS[1];
local oldVerion=tonumber(ARGV[1]);
local seconds=ARGV[2];
local fieldLen = table.getn(ARGV)-2;
local idx=1;
local argvIdx=1;
local version = redis.call('HINCRBY',key,'version','0');
if(version~=oldVerion) then
return 0;
end
for idx=1,fieldLen,2 do
argvIdx=idx+2;
redis.call('HSet',key,ARGV[argvIdx],ARGV[argvIdx+1]);
end
version =redis.call('HINCRBY',key,'version','1');
redis.call('EXPIRE',key,seconds);
return version;
2.eval直接調(diào)用測(cè)試
傳入?yún)?shù)
keysCount: 1
key: key11
version: 0
ttl: 6000
field1: icbc
field2:wh
eval "local key=KEYS[1];local oldVerion=tonumber(ARGV[1]);local seconds=ARGV[2];local fieldLen = table.getn(ARGV)-2;local idx=1;local argvIdx=1;local version = redis.call('HINCRBY',key,'version','0');if(version~=oldVerion) then return 0; end for idx=1,fieldLen,2 do argvIdx=(idx-1)+1+2; redis.call('HSet',key,ARGV[argvIdx],ARGV[argvIdx+1]); end version =redis.call('HINCRBY',key,'version','1');redis.call('EXPIRE',key,seconds);return version;" 1 key11 0 6000 field1 icbc field2 wh
3.java代碼
@Autowired
private StringRedisTemplate redisTemplate;
private static final String LUA_SCRIPT_HMSETBYVERSION = "local key=KEYS[1];
" +
"local oldVerion=tonumber(ARGV[1]);
" +
"local seconds=ARGV[2];
" +
"local fieldLen = table.getn(ARGV)-2;
" +
"local idx=1;
" +
"local argvIdx=1;
" +
"local version = redis.call('HINCRBY',key,'version','0');
" +
"if(version~=oldVerion) then
" +
" return 0;
" +
"end
" +
"for idx=1,fieldLen,2 do
" +
"argvIdx=idx+2;
" +
"redis.call('HSet',key,ARGV[argvIdx],ARGV[argvIdx+1]);
" +
"end
" +
"version =redis.call('HINCRBY',key,'version','1');
" +
"redis.call('EXPIRE',key,seconds);
" +
"return version;";
private static final String LUA_SCRIPT_HMSETBYVERSION_SHA1 = SHA1.encode(LUA_SCRIPT_HMSETBYVERSION);
public long compareAndHMset(String key, int version, Map<String, String> values, int seconds) {
if (CollectionUtils.isEmpty(values)) {
return 0;
}
List<String> keys = Collections.singletonList(key);
List<String> argvs = new ArrayList<>(values.size() * 3);
argvs.add(Integer.toString(version));
argvs.add(Integer.toString(seconds));
for (Map.Entry<String, String> item : values.entrySet()) {
argvs.add(item.getKey());
argvs.add(Strings.isNullOrEmpty(item.getValue()) ? "" : item.getValue());
}
Long result = redisTemplate.execute(new RedisCallback<Long>() {
@Override
public Long doInRedis(RedisConnection connection) throws DataAccessException {
Object nativeConnection = connection.getNativeConnection();
// 集群模式和單點(diǎn)模式雖然執(zhí)行腳本的方法一樣,但是沒有共同的接口,所以只能分開執(zhí)行
// 集群
if (nativeConnection instanceof JedisCluster) {
try {
return (Long) ((JedisCluster) nativeConnection).evalsha(LUA_SCRIPT_HMSETBYVERSION_SHA1,
keys,
argvs);
} catch (redis.clients.jedis.exceptions.JedisNoScriptException ex) {
return (Long) ((JedisCluster) nativeConnection).eval(LUA_SCRIPT_HMSETBYVERSION, keys, argvs);
} catch (Exception ex) {
return 0L;
}
} else {
// 單點(diǎn) 或 哨兵
try {
return (Long) ((Jedis) nativeConnection).evalsha(LUA_SCRIPT_HMSETBYVERSION_SHA1,
keys,
argvs);
} catch (redis.clients.jedis.exceptions.JedisNoScriptException ex) {
return (Long) ((Jedis) nativeConnection).eval(LUA_SCRIPT_HMSETBYVERSION, keys, argvs);
} catch (Exception ex) {
return 0L;
}
}
}
});
return result;
}
4.調(diào)用
return 0 < compareAndHMset("hashkey11",
1,
ImmutableMap.of("field1", "icbc2"),
6000
);
總結(jié)
以上是生活随笔為你收集整理的redis的hmset乐观锁的实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python 数据库游标,fetchma
- 下一篇: 基于Hash算法的高维数据的最近邻检索