springboot:redis+lua实现顺序⾃增的唯⼀id发号器
(springboot。。。
⼀,为什么需要⽣成唯⼀id(发号器)?
1,在分布式和微服务系统中,
springboot结构⽣成唯⼀id相对困难,
常⽤的⽅式:
uuid不具备可读性,作为主键存储时性能也不够好,
mysql的主键,在分库时使⽤不够⽅便,⾼并发时性能没有保障
所以在这⾥我们演⽰使⽤redis+lua⽣成唯⼀id
2,使⽤redis性能虽好,但仍然要考虑单点故障问题,
这⾥建议在⽣产环境中使⽤主从+哨兵或集⽅式
说明:刘宏缔的架构森林是⼀个专注架构的博客,地址:
对应的源码可以访问这⾥获取:
说明:作者:刘宏缔邮箱: 371125307@qq
⼆,本演⽰项⽬的相关信息
1,项⽬地址:
github/liuhongdi/redisuniqueid
2,项⽬原理:
利⽤redis中lua脚本的原⼦性,避免产⽣重复id的问题
3,项⽬结构:
三,lua代码说明
id.lua
local id_key = 'id_key_'..KEYS[1]
local current = redis.call('get',id_key)
if current == false then
redis.call('set',id_key,1)
return'1'
end
--redis.log(redis.LOG_NOTICE,' current:'..current..':')
local result =  tonumber(current)+1
--redis.log(redis.LOG_NOTICE,' result:'..result..':')
redis.call('set',id_key,result)
return tostring(result)
说明:
id_key变量作为存储的kv对的key
如果变量不存在,设置id_key值为1并返回
如果变量存在,值加1后返回
注意转为字符串形式后返回,⽅便java代码接收
四,java代码说明
RedisLuaUtil.java
@Service
public class RedisLuaUtil {
@Resource
private StringRedisTemplate stringRedisTemplate;
private static final Logger logger = Logger("bussniesslog");
run a lua script
luaFileName: lua file name,no path
keyList: list for redis key
return:lua return value,type is string
*/
public String runLuaScript(String luaFileName,List<String> keyList) {
DefaultRedisScript<String> redisScript = new DefaultRedisScript<>();
redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("lua/"+luaFileName)));        redisScript.setResultType(String.class);
String argsone = "none";
//String result = ute(redisScript, keyList,argsone);
String result = "";
try {
result = ute(redisScript, keyList,argsone);
} catch (Exception e) {
<("发⽣异常",e);
throw new ServiceException(ResponseCode.Msg());
}
return result;
}
}
说明:功能⽤来运⾏resource⽬录下的lua脚本
IdServiceImpl.java
@Service
public class IdServiceImpl implements IdService {
@Resource
private RedisLuaUtil redisLuaUtil;
/*
* 调⽤lua得到唯⼀id
* 返回:唯⼀的⾃增id,字符串形式
* */
@Override
public String getId(String idType) {
List<String> keyList = new ArrayList();
keyList.add(idType);
String res = redisLuaUtil.runLuaScript("id.lua",keyList);
System.out.println("-----res:"+res);
return res;
}
}
说明:得到⾃增id的service
五,测试发号器效果
1,从redis删除已创建的key
127.0.0.1:6379> del id_key_formtoken
(integer) 1
127.0.0.1:6379> get id_key_formtoken
(nil)
2,⽤ab发起测试
#-c:20个并发
#-n:共20个请求
[liuhongdi@localhost ~]$ ab -c 20 -n 20 127.0.0.1:8080/order/getid
3,查看输出效果
-----res:1
-
----res:2
-----res:3
-----res:5
-----res:6
-----res:8
-----res:7
-----res:9
-----res:10
-----res:11
-----res:12
-----res:13
-
----res:14
-----res:15
-----res:16
-----res:17
-----res:20
-----res:19
-----res:18
并发情况下,仍然正确的按⾃增的顺序⽣成id
六,查看spring boot的版本  .  ____          _            __ _ _
/\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/  ___)| |_)| | | | | || (_| |  ) ) ) )
'  |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/ :: Spring Boot ::        (v2.3.1.RELEASE)

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。