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 为例(这也是 ...
随机推荐
- Lambda表达式看这篇基本就够用了
本文讯] 2020.05.08 polo 写博不易,尊重知识! Lambda 是java8 引入的一个新特性,闭包,又叫函数式接口,下面介绍下,常用的lambda表达式方式: 所谓的将函数作为一 ...
- 10.深入k8s:调度的优先级及抢占机制源码分析
转载请声明出处哦~,本篇文章发布于luozhiyun的博客:https://www.luozhiyun.com 源码版本是1.19 上一篇我们将了获取node成功的情况,如果是一个优先pod获取nod ...
- xargs命令学习,于阮一峰博客
一.标准输入与管道命令 Unix 命令都带有参数,有些命令可以接受"标准输入"(stdin)作为参数. $ cat /etc/passwd | grep root 上面的代码使用了 ...
- 如何用canvas拍出 jDer's工作照
背景 在京东,就职满五年的老员工被称作"大佬",如果满了十年,那就要被称之为"超级大佬"了. 从 2016 年 5 月 19 日开始,每一年的这一天都被定为京东 ...
- Unity接入多个SDK的通用接口开发与资源管理(二)
接着上篇,本篇对SDK接口进行封装.在开始之前,需要先了解下面知识. (1)unity与android之间的交互 unity通过下面方式调用android中的函数: 方法一: AndroidJavaC ...
- python操作从数据库中获取数据的接口
1.输入一个表名,获取表里面的数据 2.判断用户是否存在,如果不存在就添加到数据库里面
- 如何把自己开发的项目上传到GitHub仓库或者码云仓库?
首先你需要用你的邮箱去注册一个自己的GitHub仓库 or 码云仓库.然后确保你的电脑安装了git. 码云仓库:https://gitee.com/ GitHub:https://github.com ...
- (专题一)03 matlab变量及其操作
给内存单元取名字就可以访问内存单元 变量的命名:变量名区分大小写 标准函数名以及命名方式必须用小写字母 matlab赋值语句有两种表达式 变量的管理 1.预定义变量 ans 是默认赋值变 ...
- Flutter 使用image_gallery_saver保存图片
Flutter 使用image_gallery_saver保存图片 其实我们开发项目app的时候, 你会发现有很多问题, 比如保存图片功能时 ,不仅导入包依赖包: image_gallery_sav ...
- Vant IndexBar 在小程序中的简单使用
这篇文章是老王的朋友超超提供的,上午已经更新到原创微信公众号「软件老王」,链接,欢迎各位朋友关注老王的原创公号! 先看下最终效果图,主要是渲染一个A - Z 的 通讯录.同样的,如果你要做的是城市列表 ...