如果我们需求在redis执行一系列操作且要求原子性,中间不允许其他操作执行。则可以使用lua脚本实现
StringRedisTemplate提供以下函数
public <T> T execute(RedisScript<T> script, List<K> keys, Object... args)
//script是对应Lua脚本
//keys key值队列
//args 多个参数
例如以下脚本,判断是否额度是否足够,然后进行扣减
// KEYS数组对应 List<K> keys (按照顺序获取)
// ARGV数组对应 Object... args (按照顺序获取)
//返回按照json格式返回
/**
* 单值扣减额度
*/
public static String SINGLE_REDUCE_QUOTA =
" if ARGV[1]==nil then \n"
+" return 'error'; \n"
+" else \n"
+" local quota = tonumber(redis.pcall('get', KEYS[1])) or 0; \n"
+" if quota + ARGV[1] >0 then \n"
+" redis.pcall('incrbyfloat',KEYS[1],tonumber(ARGV[1])); \n"
+" return {'success'}; \n"
+" else"
+" return {'error'}; \n"
+" end \n "
+" end \n";
调用逻辑
List keys = new ArrayList();
keys.add(prod_code);
String args1 = amt.toString();
//返回转化为List格式,然后按照顺序获取数值
List<?> ret = (List) mbop.execLua(RedisOprateScript.SINGLE_REDUCE_QUOTA ,keys,args1);
String flat = (String) ret.get(0);
if(StringUtils.equals(flat,"success")){
return true;
}else{
return false;
}
复杂返回值
//如下存在json里面嵌套json对象
"local ret_key={};local ret_value={};local remain_value={};\n"
" return {'"+REDIS_LUA_OPRATE_SUCCESS+"',ret_key,ret_value,remain_value};\n";
调用逻辑
//返回值转化
List<?> dealResult = (List) execResult;
String sign = (String) dealResult.get(0);
List<?> ret_key = (List) dealResult.get(1);
List<?> ret_value = (List) dealResult.get(2);
List<?> remain_value = (List) dealResult.get(3);