一,为什么需要生成唯一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)的更多相关文章

  1. spring boot:redis+lua实现生产环境中可用的秒杀功能(spring boot 2.2.0)

    一,秒杀需要具备的功能: 秒杀通常是电商中用到的吸引流量的促销活动方式 搭建秒杀系统,需要具备以下几点: 1,限制每个用户购买的商品数量,(秒杀价格为吸引流量一般会订的很低,不能让一个用户全部抢购到手 ...

  2. spring boot redis缓存JedisPool使用

    spring boot redis缓存JedisPool使用 添加依赖pom.xml中添加如下依赖 <!-- Spring Boot Redis --> <dependency> ...

  3. spring mvc Spring Data Redis RedisTemplate [转]

    http://maven.springframework.org/release/org/springframework/data/spring-data-redis/(spring-data包下载) ...

  4. Spring Data Redis简介以及项目Demo,RedisTemplate和 Serializer详解

    一.概念简介: Redis: Redis是一款开源的Key-Value数据库,运行在内存中,由ANSI C编写,详细的信息在Redis官网上面有,因为我自己通过google等各种渠道去学习Redis, ...

  5. SpringMVC + Spring + Mybatis+ Redis +shiro以及MyBatis学习

    SpringMVC + Spring + Mybatis+ Redis +shiro http://www.sojson.com/shiro MyBatis简介与配置MyBatis+Spring+My ...

  6. 【原】Spring整合Redis(第三篇)—盘点SDR搭建中易出现的错误

    易错点01:Spring版本过低导致的错误[环境参数]Redis版本:redis-2.4.5-win32-win64Spring原来的版本:4.1.7.RELEASESpring修改后的版本:4.2. ...

  7. spring 集成 redis -- pub/sub

    redis除了常用的当做缓存外,还可以当做简单的消息中间件,实现消息发布订阅 spring集成redis,可以使用spring-data-redis 首先引入相关maven依赖(此处我spring相关 ...

  8. Spring Boot Redis 分布式缓存的使用

    一.pom 依赖 <!-- 分布式缓存 --> <dependency> <groupId>org.springframework.boot</groupId ...

  9. Spring Boot Redis 实现分布式锁,真香!!

    之前看很多人手写分布式锁,其实 Spring Boot 现在已经做的足够好了,开箱即用,支持主流的 Redis.Zookeeper 中间件,另外还支持 JDBC. 本篇栈长以 Redis 为例(这也是 ...

随机推荐

  1. jmeter中接口测试出现乱码或不识别中文解决办法

    在查看结果是中出现乱码时:jmeter的bin目录下的jmeter.properties下最下面添加sampleresult.default.encoding=UTF-8后重新打开工具就好了 在接口的 ...

  2. [计算机网络]图解HTTP阅读笔记

    总述 书的定位:一本十分浅显的HTTP书籍,主要介绍了HTTP与HTTPS.适合入门了解,很多地方都是蜻蜓点水,但稍微深入的地方能让人了解重点在哪,后面应该有针对性地阅读深入书籍. 主要内容:介绍了T ...

  3. CentOS7使用PackageCloud安装RabbitMQ

    环境:CentOS Linux release 7.6.1810 (Core) RabbitMQ:3.7.17Erlang: 22.0.7 使用PackageCloud安装RabbitMQ是最简单的安 ...

  4. C#开发PACS医学影像处理系统(十七):2D处理之影像旋转和翻转

    1.任意角度旋转 在XAML设计器中,设置RotateTransform属性 <InkCanvas x:Name="ToolInkCanvas" UseCustomCurso ...

  5. Docker公共&本地镜像仓库(七)

    分发镜像 我们已经会构建自己的镜像了,那么如果在多个docker主机上使用镜像那?有如下的几种可用的方法: 用相同的Dockerfile在其他host上构建镜像 将镜像上传到公共registry(比如 ...

  6. vue v-for渲染数据出现DOMException: Failed to execute 'removeChild' on 'Node': The node .....

    在项目中,使用了vue的v-for渲染数组数据,在一次改变数组的时候出现异常报错,而实际的数组是已经变化过的了,页面卡死 网上找了一下原因,说是vue的DOM渲染的时候,删除之后DOM里面的还没有反应 ...

  7. 2.JAVA自带的序列化反序列化机制

  8. Laravel Model查询结果的3种存储格式内存占用对比

    PHP Laravel框架支持Model查询数据后可以有多种方式返回数据,对新手会造成一些困扰,比如数组Model对象.集合.纯数组 今天从内存占用的角度对比一下3种数据返回方式 按数组Model对象 ...

  9. java ConcurrentHashMap和CopyOnWriteArrayList解决并发问题

    ConcurrentHashMap 一.hashtable.hashmap.ConcurrentHashMap 1.线程不安全的HashMap 因为多线程环境下,使用Hashmap进行put操作会引起 ...

  10. DVWA从注入到GETSHELL

    好好过你的生活,不要老是忙着告诉别人你在干嘛. 最近在复习学过的东西,自己就重新搭了个dvwa来学习新思路,写一些简单的脚本来练习写代码的能力. 众所周知SQL注入的危害是相当大的,对于每个老司机来说 ...