public final class JedisClient {
private static final Logger LOGGER = LoggerFactory.getLogger(JedisClient .class);
private static JedisCluster jedisCluster;
private static final Map scriptSHABINDS = new HashMap();
private static final Map REDISLUAKEYPREFIX_SOURCE = new HashMap();
private JedisClient () {
}
public static void addLua(String key, String source) {
REDISLUAKEYPREFIX_SOURCE.put(key, source);
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public static synchronized void init(String jedisClusterNodes, String username, String password) {
{
scriptSHABINDS.clear();
REDISLUAKEYPREFIX_SOURCE.clear();
if (jedisCluster != null) {
try {
jedisCluster.close();
jedisCluster = null;
}
catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
}
}
if (jedisCluster != null) {
throw new RuntimeException("系统异常");
}
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
{
int core = Runtime.getRuntime().availableProcessors();
poolConfig.setMaxTotal(core * 2);
poolConfig.setMaxIdle(core);
poolConfig.setMinIdle(1);
poolConfig.setBlockWhenExhausted(false);
poolConfig.setTestWhileIdle(true);
}
String[] parts = jedisClusterNodes.split("\,");
Set nodes = new HashSet(parts.length);
for (String part : parts) {
String[] up = part.split(":");
nodes.add(new HostAndPort(up[0], Integer.parseInt(up[1])));
}
jedisCluster = new JedisCluster(nodes, 5000, 5000, 3, password, poolConfig);
}
private static String luaKeyPrefix(String keyPrefix) {
return "{" + keyPrefix + "}";
}
@SuppressWarnings("unchecked")
public static Map incrByKeys(Map map) {
if (map == null || map.isEmpty()) {
return Collections.emptyMap();
}
String luaKeyPrefix = luaKeyPrefix("RISK_REDIS_LUA");
return convertList2Map(luaKeyPrefix, (List
使用示例-init
String jedisClusterNodes = "192.168.193.1:6386,192.168.193.1:6381,192.168.193.1:6382,192.168.193.1:6383,192.168.193.1:6384,192.168.193.1:6385"; String username = "aaa"; String password = "bbb"; RiskJedisClient.init(jedisClusterNodes,username,password);
一段lua脚本
redis.replicate_commands()
local stringMatch = string.match
local tableInsert = table.insert
local redisCall = redis.call
-- 定义函数
local rsk_incrByFloat = function(key, arg)
return { key, tonumber(redisCall('INCRBYFLOAT', key, arg)) }
end
local rsk_incrByFloat_just_incrBy_mem_in_lua = function(key, arg)
local result = { 0, 0 }
local _key = string.gsub(key, "PRE_INCR_", "", 1);
return { _key, tonumber(redisCall('get', _key)) + tonumber(arg) }
end
local rsk_roster_in_lua = function(key, arg)
return { key, tonumber(redisCall('BF.EXISTS', key, arg)) }
end
-- 定义函数
local rsk_limiter = function(key, argv)
local tokens_key = "request_rate_limiter." .. key .. '.tokens'
local timestamp_key = "request_rate_limiter." .. key .. '.timestamp'
local rate = tonumber(argv[1])
local capacity = tonumber(argv[2])
local requested = tonumber(argv[3])
local now = redisCall('TIME')[1]
local ttl = math.floor(capacity / rate * 2)
local last_tokens = tonumber(redisCall("get", tokens_key))
if last_tokens == nil then
last_tokens = capacity
end
local last_refreshed = tonumber(redisCall("get", timestamp_key))
if last_refreshed == nil then
last_refreshed = 0
end
local new_tokens = math.min(capacity, last_tokens + (math.max(0, now - last_refreshed) * rate))
local allowed = 0
if new_tokens >= requested then
new_tokens = new_tokens - requested
allowed = 1
end
if ttl > 0 then
redisCall("setex", tokens_key, ttl, new_tokens)
redisCall("setex", timestamp_key, ttl, now)
end
return { key, allowed }
end
local rskUtil_merge = function(source, target)
for k, v in ipairs(source) do
tableInsert(target, v)
end
end
local rskUtil_split = function(str, sep)
local resultStrList = {}
string.gsub(str, '[^' .. sep .. ']+', function(w)
tableInsert(resultStrList, w)
end)
return resultStrList
end
local result = {}
for i = 1, #KEYS do
local key = KEYS[i]
local arg = ARGV[i]
if stringMatch(key, "{.*}LIMIT_") ~= nil then
rskUtil_merge(rsk_limiter(key, rskUtil_split(arg, ",")), result)
elseif stringMatch(key, "{.*}PRE_INCR_") ~= nil then
rskUtil_merge(rsk_incrByFloat_just_incrBy_mem_in_lua(key, arg), result)
elseif stringMatch(key, "{.*}ROSTER_") ~= nil then
rskUtil_merge(rsk_roster_in_lua(key, arg), result)
else
rskUtil_merge(rsk_incrByFloat(key, arg), result)
end
end
return result



