Redisによる一意の順序のプライマリ・キーの生成
分散型プロジェクトでは、一意のプライマリ・キーを生成したり、順序番号を生成したりするのによく使用されます.Redisによって順序番号の生成が実現されます.
あまり話さないで、直接コードをつけます.
1、唯一のキーファクトリメソッドインタフェースを生成するのは以下の通りである.
1、実現方式一
luaスクリプトは以下の通りです
あまり話さないで、直接コードをつけます.
1、唯一のキーファクトリメソッドインタフェースを生成するのは以下の通りである.
/**
*
*/
public interface SequenceFactory {
/**
*
* @param seqKey
* @return
*/
long nextValue(String seqKey);
/**
* , 24
* @param seqKey
* @return
*/
long dailyNextValue(String seqKey);
}
1、実現方式一
/**
* Lua
*/
public class RedisLuaSequenceFactory implements SequenceFactory {
private static final long SEQ_START_ID = 0L;
private static final int DEFAULT_EXPIRE = 3600 * 24;
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd");
private static final String LUA_SCRIPT = "local key = KEYS[1]
" +
"local expire = ARGV[1]
" +
"local isExp = nil ~= expire and -1 ~= tonumber(expire)
" +
"local exists = redis.call('EXISTS', key)
" +
"local seq = 0
" +
"if( exists == 0) then
" +
" redis.call('SET', key, 0)
" +
"else
" +
" seq = redis.call('INCR', key)
" +
" if( seq < 0) then
" +
" redis.call('SET', key, 0)
" +
" seq = 0
" +
" end
" +
"end
" +
"
" +
"local ttl = redis.call('TTL', key)
" +
"if( isExp and ttl == -1) then
" +
" redis.call('EXPIRE', key, expire)
" +
"end
" +
"return seq";
private Jedis jedis;
public RedisLuaSequenceFactory(Jedis jedis){
this.jedis = jedis;
}
@Override
public long nextValue(String seqKey) {
return value(seqKey, "-1");
}
@Override
public long dailyNextValue(String seqKey) {
String today = LocalDate.now().format(FORMATTER);
String key = today + ":" + seqKey;
return value(key, String.valueOf(DEFAULT_EXPIRE));
}
private long value(String key, String expire){
Object eval = jedis.eval(LUA_SCRIPT, Collections.singletonList(key), Collections.singletonList(expire));
return (Long) eval;
}
}
luaスクリプトは以下の通りです
--[[
ID
--]]
local key = KEYS[1]
local expire = ARGV[1]
local isExp = nil ~= expire and -1 ~= tonumber(expire) --
local seq = 0
local exists = redis.call('EXISTS', key) -- key
if( exists == 0) then
redis.call('SET', key, 0) -- 0
else
-- , , 0
seq = redis.call('INCR', key)
if( seq < 0) then
redis.call('SET', key, 0)
seq = 0
end
end
-- , ,
local ttl = redis.call('TTL', key)
if( isExp and ttl == -1) then
redis.call('EXPIRE', key, expire)
end
return seq