spring boot:redis+lua实现顺序自增的唯一id发号器(spring boot 2.3.1)
一,为什么需要生成唯一id(发号器)?
1,在分布式和微服务系统中,
生成唯一id相对困难,
常用的方式:
uuid不具备可读性,作为主键存储时性能也不够好,
mysql的主键,在分库时使用不够方便,高并发时性能没有保障
所以在这里我们演示使用redis+lua生成唯一id
2,使用redis性能虽好,但仍然要考虑单点故障问题,
这里建议在生产环境中使用主从+哨兵或集群方式
说明:刘宏缔的架构森林是一个专注架构的博客,地址:https://www.cnblogs.com/architectforest
对应的源码可以访问这里获取: https://github.com/liuhongdi/
说明:作者:刘宏缔 邮箱: 371125307@qq.com
二,本演示项目的相关信息
1,项目地址:
https://github.com/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 = LogManager.getLogger("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 = stringRedisTemplate.execute(redisScript, keyList,argsone);
String result = "";
try {
result = stringRedisTemplate.execute(redisScript, keyList,argsone);
} catch (Exception e) {
logger.error("发生异常",e);
throw new ServiceException(ResponseCode.LUA_ERROR.getMsg());
} 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 http://127.0.0.1:8080/order/getid
3,查看输出效果
-----res:1
-----res:2
-----res:3
-----res:4
-----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)
spring boot:redis+lua实现顺序自增的唯一id发号器(spring boot 2.3.1)的更多相关文章
- spring boot:redis+lua实现生产环境中可用的秒杀功能(spring boot 2.2.0)
一,秒杀需要具备的功能: 秒杀通常是电商中用到的吸引流量的促销活动方式 搭建秒杀系统,需要具备以下几点: 1,限制每个用户购买的商品数量,(秒杀价格为吸引流量一般会订的很低,不能让一个用户全部抢购到手 ...
- spring boot redis缓存JedisPool使用
spring boot redis缓存JedisPool使用 添加依赖pom.xml中添加如下依赖 <!-- Spring Boot Redis --> <dependency> ...
- spring mvc Spring Data Redis RedisTemplate [转]
http://maven.springframework.org/release/org/springframework/data/spring-data-redis/(spring-data包下载) ...
- Spring Data Redis简介以及项目Demo,RedisTemplate和 Serializer详解
一.概念简介: Redis: Redis是一款开源的Key-Value数据库,运行在内存中,由ANSI C编写,详细的信息在Redis官网上面有,因为我自己通过google等各种渠道去学习Redis, ...
- SpringMVC + Spring + Mybatis+ Redis +shiro以及MyBatis学习
SpringMVC + Spring + Mybatis+ Redis +shiro http://www.sojson.com/shiro MyBatis简介与配置MyBatis+Spring+My ...
- 【原】Spring整合Redis(第三篇)—盘点SDR搭建中易出现的错误
易错点01:Spring版本过低导致的错误[环境参数]Redis版本:redis-2.4.5-win32-win64Spring原来的版本:4.1.7.RELEASESpring修改后的版本:4.2. ...
- spring 集成 redis -- pub/sub
redis除了常用的当做缓存外,还可以当做简单的消息中间件,实现消息发布订阅 spring集成redis,可以使用spring-data-redis 首先引入相关maven依赖(此处我spring相关 ...
- Spring Boot Redis 分布式缓存的使用
一.pom 依赖 <!-- 分布式缓存 --> <dependency> <groupId>org.springframework.boot</groupId ...
- Spring Boot Redis 实现分布式锁,真香!!
之前看很多人手写分布式锁,其实 Spring Boot 现在已经做的足够好了,开箱即用,支持主流的 Redis.Zookeeper 中间件,另外还支持 JDBC. 本篇栈长以 Redis 为例(这也是 ...
随机推荐
- C#托管堆和非托管堆
- 吴恩达《深度学习》-课后测验-第五门课 序列模型(Sequence Models)-Week 2: Natural Language Processing and Word Embeddings (第二周测验:自然语言处理与词嵌入)
Week 2 Quiz: Natural Language Processing and Word Embeddings (第二周测验:自然语言处理与词嵌入) 1.Suppose you learn ...
- [LeetCode]152. 乘积最大子序列(DP)
题目 给定一个整数数组 nums ,找出一个序列中乘积最大的连续子序列(该序列至少包含一个数). 示例 1: 输入: [2,3,-2,4] 输出: 6 解释: 子数组 [2,3] 有最大乘积 6. 示 ...
- google protocol buffer——protobuf的问题和改进2
这一系列文章主要是对protocol buffer这种编码格式的使用方式.特点.使用技巧进行说明,并在原生protobuf的基础上进行扩展和优化,使得它能更好地为我们服务. 在上一篇文章中,我们举例了 ...
- 本周 GitHub 速览:您的代码有声儿吗?(Vol.38)
作者:HelloGitHub-小鱼干 摘要:还记得花式夸赞程序员的彩虹屁插件 vscode-rainbow-fart 吗?它后续有人啦!JazzIt 同它的前辈 vscode-rainbow-fart ...
- Flutter学习四之实现一个支持刷新加载的列表
上一篇文章用Scaffold widget搭建了一个带底部导航栏的的项目架构,这篇文章就来介绍一下在flutter中怎么实现一个带下拉刷新和上拉加载更多的一个列表,这里用到了pull_to_refre ...
- python爬取花木兰豆瓣影评,并进行词云分析
前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理. PS:如有需要Python学习资料的小伙伴可以加点击下方链接自行获取 python免费学习资 ...
- jfinal3连接sqlserver2012 保存日期字段出现“不支持从 UNKNOWN 到 UNKNOWN 的转换”错误
修改Dialect中的fillStatement方法,增加判断日期类型并转换为时间戳
- 安装MySQL和出现的问题解决
在Windows下安装mysql,注意自己的Windows是32位还是64位. MySQL官网下载地址:https://dev.mysql.com/downloads/mysql/ 下载完之后,解压放 ...
- noSql 的应用场景简述
选型一定要结合实际情况而不是照本宣科,比如: 企业发展之初,明明一个关系型数据库就能搞定且支撑一年的架构,搞一套大而全的技术方案出来 有一些数据条件查询多,更适合使用ElasticSearch做存储降 ...