import com.alibaba.fastjson.JSON;
import com.juxiao.xchat.dao.room.dto.CallStatus;
import com.juxiao.xchat.manager.cache.redis.RedissonManager;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.*;
import org.redisson.client.protocol.ScoredEntry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@Slf4j
@Service
public class RedissonManagerImpl implements RedissonManager {
@Autowired
private RedissonClient redissonClient;
@Override
public RLock lock(String key, int waitTime, int lockTimeout) {
RLock rLock = redissonClient.getLock(key);
try {
if (rLock.tryLock(waitTime, lockTimeout, TimeUnit.SECONDS)) {
return rLock;
}
} catch (InterruptedException e) {
log.error("[ Redisson ] tryLock err:", e);
}
return null;
}
@Override
public RLock fairLock(String key, int waitTime, int lockTimeout) {
RLock rLock = redissonClient.getFairLock(key);
try {
if (rLock.tryLock(waitTime, lockTimeout, TimeUnit.SECONDS)) {
return rLock;
}
} catch (InterruptedException e) {
log.error("[ Redisson ] tryLock err:", e);
}
return null;
}
@Override
public long del(String... key) {
RKeys rKeys = redissonClient.getKeys();
return rKeys.delete(key);
}
@Override
public boolean expire(String key, long time, TimeUnit timeUnit) {
RKeys rKeys = redissonClient.getKeys();
return rKeys.expire(key, time, timeUnit);
}
@Override
public Iterable<String> keys(String key) {
RKeys rKeys = redissonClient.getKeys();
return rKeys.getKeysByPattern(key);
}
@Override
public boolean exists(String key) {
RBucket<String> rBucket = redissonClient.getBucket(key);
return rBucket.isExists();
}
@Override
public Long getExpire(String key) {
RKeys rKeys = redissonClient.getKeys();
return rKeys.remainTimeToLive(key);
}
@Override
public long ttl(String key) {
RBucket<String> rBucket = redissonClient.getBucket(key);
return rBucket.remainTimeToLive();
}
@Override
public String get(String key) {
RBucket<String> rBucket = redissonClient.getBucket(key);
return rBucket.get();
}
@Override
public Map<String, String> mGet(String... key) {
RBuckets rBuckets = redissonClient.getBuckets();
return rBuckets.get(key);
}
@Override
public void set(String key, String value) {
RBucket<String> rBucket = redissonClient.getBucket(key);
rBucket.set(value);
}
@Override
public String getAndSet(String key, String value) {
RBucket<String> rBucket = redissonClient.getBucket(key);
return rBucket.getAndSet(value);
}
@Override
public String getAndDelete(String key) {
RBucket<String> rBucket = redissonClient.getBucket(key);
return rBucket.getAndDelete();
}
@Override
public void set(String key, String value, int time, TimeUnit timeUnit) {
RBucket<String> rBucket = redissonClient.getBucket(key);
rBucket.set(value, time, timeUnit);
}
@Override
public void set(String key, String value, long time, TimeUnit timeUnit) {
RBucket<String> rBucket = redissonClient.getBucket(key);
rBucket.set(value, time, timeUnit);
}
@Override
public boolean setnx(String key, String value) {
RBucket<String> rBucket = redissonClient.getBucket(key);
return rBucket.trySet(value);
}
@Override
public boolean setnx(String key, String value, long time, TimeUnit timeUnit) {
RBucket<String> rBucket = redissonClient.getBucket(key);
return rBucket.trySet(value, time, timeUnit);
}
@Override
public boolean msetnx(Map<String, String> map) {
RBuckets rBuckets = redissonClient.getBuckets();
return rBuckets.trySet(map);
}
@Override
public boolean msetnx(String key, String otherKey, String value, String otherValue) {
Map<String, String> map = new HashMap<>();
map.put(key, value);
map.put(otherKey, otherValue);
return msetnx(map);
}
private final static String SCRIPT_1 =
"local v1 = redis.call('SETNX',KEYS[1],ARGV[1]); " +
"local v2 = redis.call('SETNX',KEYS[2],ARGV[2]); " +
"return v1 + v2; ";
@Override
public Long setnx(String key, String otherKey, String value, String otherValue) {
RScript rScript = redissonClient.getScript();
List<Object> list = new ArrayList<>();
list.add(key);
list.add(otherKey);
List<Object> params = new ArrayList(2);
params.add(value);
params.add(otherValue);
return rScript.eval(RScript.Mode.READ_WRITE, SCRIPT_1, RScript.ReturnType.INTEGER, list, params.toArray());
}
private final static String SCRIPT_2 = "local val = redis.call('MSETNX',KEYS[1],ARGV[1],KEYS[2],ARGV[2]) " +
"if val == 0 then " +
" return 0 " +
"else " +
" redis.call('Expire', KEYS[1],ARGV[3]) " +
" redis.call('Expire', KEYS[2],ARGV[3]) " +
" return 1 " +
"end";
@Override
public Long msetnx(String key, String otherKey, String value, String otherValue, String timeoutSeconds) {
RScript rScript = redissonClient.getScript();
List<Object> list = new ArrayList<>();
list.add(key);
list.add(otherKey);
List<Object> params = new ArrayList(2);
params.add(value);
params.add(otherValue);
params.add(timeoutSeconds);
return rScript.eval(RScript.Mode.READ_WRITE, SCRIPT_2, RScript.ReturnType.INTEGER, list, params.toArray());
}
@Override
public Long increment(String key, Long value) {
RAtomicLong rAtomicLong = redissonClient.getAtomicLong(key);
return rAtomicLong.addAndGet(value);
}
@Override
public Double increment(String key, Double value) {
RAtomicDouble rAtomicDouble = redissonClient.getAtomicDouble(key);
return rAtomicDouble.addAndGet(value);
}
@Override
public long incrByTime(String key, int timeout) {
RAtomicLong rAtomicLong = redissonClient.getAtomicLong(key);
long result = rAtomicLong.addAndGet(1);
rAtomicLong.expire(timeout, TimeUnit.SECONDS);
return result;
}
@Override
public String hGet(String key, String field) {
RMap<String, String> rMap = redissonClient.getMap(key);
return rMap.get(field);
}
@Override
public Map<String, String> hMGet(String key, Set<String> field) {
RMap<String, String> rMap = redissonClient.getMap(key);
return rMap.getAll(field);
}
@Override
public Map<String, String> hGetAll(String key) {
RMap<String, String> rMap = redissonClient.getMap(key);
return rMap.readAllMap();
}
@Override
public int hLen(String key) {
RMap<String, String> rMap = redissonClient.getMap(key);
return rMap.size();
}
@Override
public String hSet(String key, String field, String value) {
RMap<String, String> rMap = redissonClient.getMap(key);
return rMap.put(field, value);
}
@Override
public void hSetAll(String key, Map<String, String> value) {
RMap<String, String> rMap = redissonClient.getMap(key);
rMap.putAll(value);
}
@Override
public String hSet(String key, String field, String value, int time, TimeUnit timeUnit) {
RMapCache<String, String> rMapCache = redissonClient.getMapCache(key);
return rMapCache.put(field, value, time, timeUnit);
}
@Override
public boolean hSetIfAbsent(String key, String field, String value) {
RMap<String, String> rMap = redissonClient.getMap(key);
return rMap.fastPutIfAbsent(field, value);
}
@Override
public Integer hIncrement(String key, String field, Integer value) {
RMap<String, Integer> rMap = redissonClient.getMap(key);
return rMap.addAndGet(field, value);
}
@Override
public Long hIncrement(String key, String field, Long value) {
RMap<String, Long> rMap = redissonClient.getMap(key);
return rMap.addAndGet(field, value);
}
@Override
public Double hIncrement(String key, String field, Double value) {
RMap<String, Double> rMap = redissonClient.getMap(key);
return rMap.addAndGet(field, value);
}
@Override
public String hDel(String key, String field) {
RMap<String, String> rMap = redissonClient.getMap(key);
return rMap.remove(field);
}
@Override
public Long hDelKeys(String key, String[] fields) {
RMap<String, String> rMap = redissonClient.getMap(key);
return rMap.fastRemove(fields);
}
@Override
public Set<String> hKeys(String key) {
RMap<String, String> rMap = redissonClient.getMap(key);
return rMap.keySet();
}
@Override
public boolean pushAll(String key, List<String> values) {
RList<String> rList = redissonClient.getList(key);
return rList.addAll(values);
}
@Override
public void leftPush(String key, String value) {
RDeque<String> rDeque = redissonClient.getDeque(key);
rDeque.addFirst(value);
}
@Override
public String leftPop(String key) {
RDeque<String> rDeque = redissonClient.getDeque(key);
return rDeque.pollFirst();
}
@Override
public List<String> lPop(String key, int size) {
RDeque<String> rDeque = redissonClient.getDeque(key);
return rDeque.pollFirst(size);
}
@Override
public void rightPush(String key, String value) {
RDeque<String> rDeque = redissonClient.getDeque(key);
rDeque.addLast(value);
}
@Override
public int rPush(String key, String[] value) {
RDeque<String> rDeque = redissonClient.getDeque(key);
return rDeque.addFirstIfExists(value);
}
@Override
public String rightPop(String key) {
RDeque<String> rDeque = redissonClient.getDeque(key);
return rDeque.pollLast();
}
@Override
public boolean lRemove(String key, Integer count, String value) {
RList<String> rList = redissonClient.getList(key);
return rList.remove(value, count);
}
@Override
public List<String> lRange(String key, int start, int end) {
RList<String> rList = redissonClient.getList(key);
return rList.range(start, end);
}
@Override
public int lSize(String key) {
RDeque<String> rDeque = redissonClient.getDeque(key);
return rDeque.size();
}
@Override
public List<String> listAll(String key) {
RDeque<String> rDeque = redissonClient.getDeque(key);
return rDeque.readAll();
}
@Override
public boolean zAdd(String key, String field, double score) {
RScoredSortedSet<String> rScoredSortedSet = redissonClient.getScoredSortedSet(key);
return rScoredSortedSet.add(score, field);
}
@Override
public boolean zAdd(String key, double score, String field) {
RScoredSortedSet<String> rScoredSortedSet = redissonClient.getScoredSortedSet(key);
return rScoredSortedSet.add(score, field);
}
@Override
public int zAddAll(String key, Map<String, Double> map) {
RScoredSortedSet<String> rScoredSortedSet = redissonClient.getScoredSortedSet(key);
return rScoredSortedSet.addAll(map);
}
@Override
public Double zIncrement(String key, String field, Double score) {
RScoredSortedSet<String> rScoredSortedSet = redissonClient.getScoredSortedSet(key);
return rScoredSortedSet.addScore(field, score);
}
@Override
public Double zIncrement(String key, Double score, String field) {
RScoredSortedSet<String> rScoredSortedSet = redissonClient.getScoredSortedSet(key);
return rScoredSortedSet.addScore(field, score);
}
@Override
public Double zIncrement(String key, Long score, String field) {
RScoredSortedSet<String> rScoredSortedSet = redissonClient.getScoredSortedSet(key);
return rScoredSortedSet.addScore(field, score);
}
private final static String ZINCRBY_IF_EXISTS = "local val = redis.call('ZRANK',KEYS[1],ARGV[1]) " +
"if val == false or val == nil then " +
" return nil " +
"else " +
" return redis.call('ZINCRBY', KEYS[1],ARGV[2],ARGV[1]) " +
"end";
@Override
public String zincrbyIfExists(String key, String member, double increment) {
RScript rScript = redissonClient.getScript();
List<Object> list = new ArrayList<>();
list.add(key);
List<Object> params = new ArrayList(2);
params.add(member);
params.add(increment);
return rScript.eval(RScript.Mode.READ_WRITE, ZINCRBY_IF_EXISTS, RScript.ReturnType.VALUE, list, params.toArray());
}
@Override
public Integer zRank(String key, String field) {
RScoredSortedSet<String> rScoredSortedSet = redissonClient.getScoredSortedSet(key);
return rScoredSortedSet.rank(field);
}
@Override
public Integer reverseZRank(String key, String field) {
RScoredSortedSet<String> rScoredSortedSet = redissonClient.getScoredSortedSet(key);
return rScoredSortedSet.revRank(field);
}
@Override
public int zCard(String key) {
RScoredSortedSet<String> rScoredSortedSet = redissonClient.getScoredSortedSet(key);
return rScoredSortedSet.size();
}
@Override
public Double zScore(String key, String field) {
RScoredSortedSet<String> rScoredSortedSet = redissonClient.getScoredSortedSet(key);
return rScoredSortedSet.getScore(field);
}
@Override
public boolean zRemove(String key, String field) {
RScoredSortedSet<String> rScoredSortedSet = redissonClient.getScoredSortedSet(key);
return rScoredSortedSet.remove(field);
}
@Override
public int zRemoveByScore(String key, double min, double max) {
RScoredSortedSet<String> rScoredSortedSet = redissonClient.getScoredSortedSet(key);
return rScoredSortedSet.removeRangeByScore(min, true, max, true);
}
@Override
public int removeRange(String key, int start, int end) {
RScoredSortedSet<String> rScoredSortedSet = redissonClient.getScoredSortedSet(key);
return rScoredSortedSet.removeRangeByRank(start, end);
}
@Override
public int removeRangeByScore(String key, double min, double max) {
RScoredSortedSet<String> rScoredSortedSet = redissonClient.getScoredSortedSet(key);
return rScoredSortedSet.removeRangeByScore(min, true, max, true);
}
@Override
public boolean zRemoveAll(String key, List<String> fieldList) {
RScoredSortedSet<String> rScoredSortedSet = redissonClient.getScoredSortedSet(key);
return rScoredSortedSet.removeAll(fieldList);
}
@Override
public Integer getZetSize(String key) {
RScoredSortedSet<String> rScoredSortedSet = redissonClient.getScoredSortedSet(key);
return rScoredSortedSet.size();
}
@Override
public long zcount(String key, double min, double max) {
RScoredSortedSet<String> rScoredSortedSet = redissonClient.getScoredSortedSet(key);
return rScoredSortedSet.count(min, true, max, true);
}
@Override
public Collection<ScoredEntry<String>> zRange(String key, int start, int end) {
RScoredSortedSet<String> rScoredSortedSet = redissonClient.getScoredSortedSet(key);
return rScoredSortedSet.entryRange(start, end);
}
@Override
public Collection<ScoredEntry<String>> reverseZRange(String key, int start, int end) {
RScoredSortedSet<String> rScoredSortedSet = redissonClient.getScoredSortedSet(key);
return rScoredSortedSet.entryRangeReversed(start, end);
}
@Override
public Collection<ScoredEntry<String>> zRangeByScore(String key, double min, double max) {
RScoredSortedSet<String> rScoredSortedSet = redissonClient.getScoredSortedSet(key);
return rScoredSortedSet.entryRange(min, true, max, true);
}
@Override
public Collection<ScoredEntry<String>> reverseZRangeByScore(String key, double min, double max) {
RScoredSortedSet<String> rScoredSortedSet = redissonClient.getScoredSortedSet(key);
return rScoredSortedSet.entryRangeReversed(min, true, max, true);
}
@Override
public Collection<String> zrangeByScore(String key, double min, double max) {
RScoredSortedSet<String> rScoredSortedSet = redissonClient.getScoredSortedSet(key);
return rScoredSortedSet.valueRange(min, true, max, true);
}
@Override
public Collection<String> zrevRangeByScore(String key, double max, double min) {
RScoredSortedSet<String> rScoredSortedSet = redissonClient.getScoredSortedSet(key);
return rScoredSortedSet.valueRangeReversed(min, true, max, true);
}
@Override
public Collection<String> zrange(String key, int start, int end) {
RScoredSortedSet<String> rScoredSortedSet = redissonClient.getScoredSortedSet(key);
return rScoredSortedSet.valueRange(start, end);
}
@Override
public Collection<String> zrevrange(String key, long start, long end) {
RScoredSortedSet<String> rScoredSortedSet = redissonClient.getScoredSortedSet(key);
return rScoredSortedSet.valueRangeReversed((int) start, (int) end);
}
@Override
public boolean sExists(String key) {
RSet<String> rSet = redissonClient.getSet(key);
return rSet.isExists();
}
@Override
public boolean sIsMember(String key, String field) {
RSet<String> rSet = redissonClient.getSet(key);
return rSet.contains(field);
}
@Override
public boolean sAdd(String key, String field) {
RSet<String> rSet = redissonClient.getSet(key);
return rSet.add(field);
}
@Override
public boolean sAddAll(String key, Collection<String> field) {
RSet<String> rSet = redissonClient.getSet(key);
return rSet.addAll(field);
}
@Override
public boolean sRemove(String key, String field) {
RSet<String> rSet = redissonClient.getSet(key);
return rSet.remove(field);
}
@Override
public Set<String> sPop(String key, int size) {
RSet<String> rSet = redissonClient.getSet(key);
return rSet.removeRandom(size);
}
@Override
public int sCard(String key) {
RSet<String> rSet = redissonClient.getSet(key);
return rSet.size();
}
@Override
public Set<String> sMembers(String key) {
RSet<String> rSet = redissonClient.getSet(key);
return rSet.readAll();
}
@Override
public long sAddAndCard(String key, String field) {
String script = "redis.call('sAdd', KEYS[1], ARGV[1]); " +
"return redis.call('sCard', KEYS[1]); ";
RScript rscript = redissonClient.getScript();
return rscript.eval(RScript.Mode.READ_WRITE, script, RScript.ReturnType.INTEGER,
Collections.singletonList(key), field);
}
@Override
public boolean hSetIfExist(String key, String field, String value) {
String script = "local n = redis.call('hGet', KEYS[1], ARGV[1]); " +
"if n then " +
"redis.call('hSet', KEYS[1], ARGV[1], ARGV[2]); " +
"return true;" +
"else " +
"return false;" +
"end; ";
RScript rscript = redissonClient.getScript();
return rscript.eval(RScript.Mode.READ_WRITE, script, RScript.ReturnType.BOOLEAN,
Collections.singletonList(key), field, value);
}
@Override
public String luaKeepIncrement(String key, Long num) {
if(num == null) {
return null;
}
String script = "local last = redis.call('get', KEYS[1]); " +
"if not last or tonumber(ARGV[1]) > tonumber(last) then " +
"redis.call('set', KEYS[1], ARGV[1]); " +
"end; " +
"return last; ";
RScript rscript = redissonClient.getScript();
return rscript.eval(RScript.Mode.READ_WRITE, script, RScript.ReturnType.VALUE,
Collections.singletonList(key), num);
}
@Override
public Long luaDoubleAddUp(String key, Double val, boolean end) {
if(val == null) {
return null;
}
String script = "local v = redis.call('incrbyfloat', KEYS[1], ARGV[1]); " +
"local t1, t2 = math.modf(v);" +
"if ARGV[2] == 'true' then " +
"redis.call('del', KEYS[1]);" +
"else " +
"redis.call('set', KEYS[1], t2);" +
"end; " +
"return t1;";
RScript rscript = redissonClient.getScript();
return rscript.eval(RScript.Mode.READ_WRITE, script, RScript.ReturnType.VALUE,
Collections.singletonList(key), val, end);
}
@Override
public String couponsOperator(String key, long now, boolean reduce, CallStatus.Coupons value) {
String script = "while true do " +
" local r = redis.call('lpop', KEYS[1]); " +
" if not r then break; end; " +
" local json = cjson.decode(r); " +
" if json.expireTime > tonumber(ARGV[1]) then " +
" if ARGV[2] == 'true' then return r; end; " +
" redis.call('lpush', KEYS[1], r); break; " +
" end; " +
" end; " +
" local v = ARGV[3]; if v ~= '' then redis.call('rpush', KEYS[1], v); end; " +
" return v; ";
RScript rscript = redissonClient.getScript();
return rscript.eval(RScript.Mode.READ_WRITE, script, RScript.ReturnType.VALUE,
Collections.singletonList(key), now, reduce,
value == null ? "" : JSON.toJSONString(value));
}
@Override
public void fixSizeListAdd(String key, String value, int limit) {
String script = "local t = redis.call('llen', KEYS[1]);" +
"if (t >= tonumber(ARGV[2])) then " +
"redis.call('rpop', KEYS[1]); end; " +
"redis.call('lpush', KEYS[1], ARGV[1]); ";
RScript rscript = redissonClient.getScript();
rscript.eval(RScript.Mode.READ_WRITE, script, RScript.ReturnType.BOOLEAN, Collections.singletonList(key), value, limit);
}
/**
* 数据量不大的情况下,首页也可以考虑这种方式获取排序的数据。
* @param key
* @param language
* @param country
* @return
*/
@Override
public String sortTable(String key, String language, String country) {
String script = "local t = redis.call('hgetall', KEYS[1]);\n" +
"local arr = {};\n" +
"for i, v in pairs(t) do\n" +
" if i % 2 == 0 then\n" +
" local j = cjson.decode(v)\n" +
" if j.language == ARGV[1] then j.languageEquals = 1 else j.languageEquals = 0 end;\n" +
" if j.country == ARGV[2] then j.countryEquals = 1 else j.countryEquals = 0 end;\n" +
" table.insert(arr, j)\n" +
" end \n" +
"end \n" +
"table.sort(arr, function (a, b) \n" +
" local ta = a.languageEquals + a.countryEquals; \n" +
" local tb = b.languageEquals + b.countryEquals; \n" +
" if ta > 0 then ta = 1 end; \n" +
" if tb > 0 then tb = 1 end; \n" +
" if ta - tb == 0 then \n" +
" return a.createTime < b.createTime \n" +
" else " +
" return ta > tb end;\n" +
"end)\n" +
"return cjson.encode(arr); \n";
RScript rscript = redissonClient.getScript();
return rscript.eval(RScript.Mode.READ_WRITE, script, RScript.ReturnType.VALUE,
Collections.singletonList(key), language, country);
}
@Override
public String hSetIsNull(String key, String field, String value) {
String script = "local t = redis.call('hget', KEYS[1], ARGV[1]);\n" +
"if t then return t; else redis.call('hset', KEYS[1], ARGV[1], ARGV[2]); return t; end;";
RScript rscript = redissonClient.getScript();
return rscript.eval(RScript.Mode.READ_WRITE, script, RScript.ReturnType.VALUE,
Collections.singletonList(key), field, value);
}
@Override
public String setIsNull(String key, String value) {
String script = "local t = redis.call('get', KEYS[1]);\n" +
"if t then return t; else redis.call('set', KEYS[1], ARGV[1]); return t; end;";
RScript rscript = redissonClient.getScript();
return rscript.eval(RScript.Mode.READ_WRITE, script, RScript.ReturnType.VALUE,
Collections.singletonList(key), value);
}
@Override
public String updateJson(String key, String field, long num, long limit) {
String script = "local t = redis.call('get', KEYS[1]);\n" +
"local j;\n" +
"if t then j = cjson.decode(t); else j = cjson.decode(\"{}\"); end;\n" +
"local n;\n" +
"if j[ARGV[3]] then n = tonumber(j[ARGV[3]]); else n = 0 end;\n" +
"local r = n + tonumber(ARGV[1]);\n" +
"local limit = tonumber(ARGV[2]);\n" +
"if r >= 0 and (limit < 0 or r <= limit) then j[ARGV[3]] = r; " +
"redis.call('set', KEYS[1], cjson.encode(j)); end;\n" +
"j[ARGV[3]] = r;" +
"return cjson.encode(j);";
RScript rscript = redissonClient.getScript();
return rscript.eval(RScript.Mode.READ_WRITE, script, RScript.ReturnType.VALUE,
Collections.singletonList(key), num, limit, field);
}
@Override
public String updateJson(String key, String field, String value) {
String script = "local t = redis.call('get', KEYS[1]);\n" +
"local j;\n" +
"if t then j = cjson.decode(t); else j = cjson.decode(\"{}\"); end;\n" +
"j[ARGV[1]] = ARGV[2]; " +
"redis.call('set', KEYS[1], cjson.encode(j));\n" +
"return cjson.encode(j);";
RScript rscript = redissonClient.getScript();
return rscript.eval(RScript.Mode.READ_WRITE, script, RScript.ReturnType.VALUE,
Collections.singletonList(key), field, value);
}
@Override
public String hUpdateJson(String key, String uid, String field, long num, long limit) {
String script = "local t = redis.call('hget', KEYS[1], ARGV[4]);\n" +
"local j;\n" +
"if t then j = cjson.decode(t); else j = cjson.decode(\"{}\"); end;\n" +
"local n;\n" +
"if j[ARGV[3]] then n = tonumber(j[ARGV[3]]); else n = 0 end;\n" +
"local r = n + tonumber(ARGV[1]);\n" +
"local limit = tonumber(ARGV[2]);\n" +
"if r >= 0 and (limit < 0 or r <= limit) then j[ARGV[3]] = r; " +
"redis.call('hset', KEYS[1], ARGV[4], cjson.encode(j)); end;\n" +
"j[ARGV[3]] = r;" +
"return cjson.encode(j);";
RScript rscript = redissonClient.getScript();
return rscript.eval(RScript.Mode.READ_WRITE, script, RScript.ReturnType.VALUE,
Collections.singletonList(key), num, limit, field, uid);
}
@Override
public String mUpdateJson(String key, List<String> field, List<Number> num, List<Long> limit) {
if(field == null || num == null || limit == null) {
throw new RuntimeException("mUpdateJson param error, has null, field: " + field + " num:" + num + " limit: " + limit);
}
field = field.stream().filter(Objects::nonNull).collect(Collectors.toList());
num = num.stream().filter(Objects::nonNull).collect(Collectors.toList());
limit = limit.stream().filter(Objects::nonNull).collect(Collectors.toList());
if(field.size() > 100) {
throw new RuntimeException("mUpdateJson operator field length not > 100!");
}
if(field.size() != num.size() || field.size() != limit.size()) {
throw new RuntimeException("mUpdateJson param size error, fieldSize: " + field.size() + " numSize:"
+ num.size() + " limitSize: " + limit.size());
}
String script = "local t = redis.call('get', KEYS[1]);\n" +
"local j; local err = false;\n" +
"if t then j = cjson.decode(t); else j = cjson.decode(\"{}\"); end;\n" +
"local n;\n" +
"for i = 1, #ARGV, 3 do \n" +
"if j[ARGV[i]] then n = tonumber(j[ARGV[i]]); else n = 0 end;\n" +
"local r = n + tonumber(ARGV[i + 1]);\n" +
"local limit = tonumber(ARGV[i + 2]);\n" +
"if (r >= 0 or r > n) and (limit < 0 or r <= limit) then j[ARGV[i]] = r;\n" +
"else j[ARGV[i]] = r; err = true; j['error'] = 1; end;\n" +
"end; \n" +
"local er = cjson.encode(j);\n" +
"if err then return er;\n" +
"else redis.call('set', KEYS[1], er); return er end;";
RScript rscript = redissonClient.getScript();
int size = field.size();
Object[] param = new Object[size * 3];
for(int i = 0;i < size;i++) {
param[3 * i] = field.get(i);
param[3 * i + 1] = num.get(i);
param[3 * i + 2] = limit.get(i);
}
return rscript.eval(RScript.Mode.READ_WRITE, script, RScript.ReturnType.VALUE, Collections.singletonList(key), param);
}
@Override
public void listDel(String key, String value) {
String script = "local t = redis.call('LRANGE', KEYS[1], 0, -1); " +
"if t then " +
"local len = 0; " +
"for i=1, #t do " +
" if (t[i] == ARGV[1]) then table.remove(t, i); len = len - 1; end;" +
" len = len + 1; " +
"end; " +
"redis.call('del', KEYS[1]); " +
"if len > 0 then redis.call('RPUSH', KEYS[1], unpack(t)); end;" +
"end;";
RScript rscript = redissonClient.getScript();
rscript.eval(RScript.Mode.READ_WRITE, script, RScript.ReturnType.BOOLEAN, Collections.singletonList(key), value);
}
@Override
public List<Long> sAddAndExpire(String key, String field, long time, TimeUnit timeUnit) {
String script = "local t = redis.call('sadd', KEYS[1], ARGV[1]);" +
"local time = redis.call('ttl', KEYS[1]);" +
"if not time or tonumber(time) <= 0 then redis.call('EXPIRE', KEYS[1], ARGV[2]); end;" +
"return {t, redis.call('scard', KEYS[1])}; ";
RScript rscript = redissonClient.getScript();
return rscript.eval(RScript.Mode.READ_WRITE, script, RScript.ReturnType.MULTI, Collections.singletonList(key), field, timeUnit.toMillis(time)/1000);
}
@Override
public String hSetAndExpire(String key, String field, String value, long time, TimeUnit timeUnit) {
String script = "local t = redis.call('hget', KEYS[1], ARGV[1]);" +
"redis.call('hset', KEYS[1], ARGV[1], ARGV[2]);" +
"local time = redis.call('ttl', KEYS[1]);" +
"if not time or tonumber(time) <= 0 then redis.call('EXPIRE', KEYS[1], ARGV[3]); end;" +
"return t; ";
RScript rscript = redissonClient.getScript();
return rscript.eval(RScript.Mode.READ_WRITE, script, RScript.ReturnType.VALUE, Collections.singletonList(key), field, value, timeUnit.toMillis(time)/1000);
}
@Override
public boolean zAddAndExpire(String key, String field, double score, long time, TimeUnit timeUnit) {
String script = "local t = redis.call('zadd', KEYS[1], ARGV[1], ARGV[2]);" +
"local time = redis.call('ttl', KEYS[1]);" +
"if not time or tonumber(time) <= 0 then redis.call('EXPIRE', KEYS[1], ARGV[3]); end;" +
"return t; ";
RScript rscript = redissonClient.getScript();
return rscript.eval(RScript.Mode.READ_WRITE, script, RScript.ReturnType.BOOLEAN, Collections.singletonList(key), field, score, timeUnit.toMillis(time)/1000);
}
@Override
public Long incrementAndExpire(String key, Long value, long time, TimeUnit timeUnit) {
String script = "local t = redis.call('INCRBY', KEYS[1], ARGV[1]);" +
"local time = redis.call('ttl', KEYS[1]);" +
"if not time or tonumber(time) <= 0 then redis.call('EXPIRE', KEYS[1], ARGV[2]); end;" +
"return t; ";
RScript rscript = redissonClient.getScript();
return rscript.eval(RScript.Mode.READ_WRITE, script, RScript.ReturnType.INTEGER, Collections.singletonList(key), value, timeUnit.toMillis(time)/1000);
}
@Override
public Long hIncrementAndExpire(String key, String field, Long score, long time, TimeUnit timeUnit) {
String script = "local t = redis.call('HINCRBY', KEYS[1], ARGV[1], ARGV[2]);" +
"local time = redis.call('ttl', KEYS[1]);" +
"if not time or tonumber(time) <= 0 then redis.call('EXPIRE', KEYS[1], ARGV[3]); end;" +
"return t; ";
RScript rscript = redissonClient.getScript();
return rscript.eval(RScript.Mode.READ_WRITE, script, RScript.ReturnType.INTEGER, Collections.singletonList(key), field, score, timeUnit.toMillis(time)/1000);
}
}