一,为什么需要生成唯一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. jzoj1497. 景点中心

    Description 话说宁波市的中小学生在镇海中学参加计算机程序设计比赛,比赛之余,他们在镇海中学的各个景点参观.镇海中学共有n个景点,每个景点均有若干学生正在参观.这n个景点以自然数1至n编号, ...

  2. Unity3D与iOS的交互

    1. 关于Unity3D Unity3D(以下简称U3D)是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏.建筑可视化.实时三维动画等类型互动内容的多平台的综合型游戏开 ...

  3. day52:django:ORM单表/多表操作

    目录 1.ORM 2.ORM单表增删改查 13个必知必会的查询接口 filter基于双下划线的模糊查询 3.ORM多表增删改查 ORM 什么是ORM? ORM(object relational ma ...

  4. Fork Join 并发任务执行框架

    Fork Join 体现了分而治之 什么是分而治之? 规模为N的问题,如果N<阈值,直接解决,N>阈值,将N分解为K个小规模子问题,子问题互相对立,与原问题形式相同,将子问题的解合并得到原 ...

  5. k8s Docker 安装

    k8s Docker 安装 一.运行环境 Centos 7.7 虚拟机内核为 3.10 基础组件版本: k8s.gcr.io/kube-apiserver:v1.16.0 k8s.gcr.io/kub ...

  6. Oracle学习(十六)Oracle安装

    为了本地创建数据库自己玩耍,还是下个Oracle的客户端吧... 一.下载地址 注意,要用Oracle的帐号进行登录后才能下载 http://download.oracle.com/otn/nt/or ...

  7. 针对于Java的35 个代码性能优化总结

    针对于Java的35 个代码性能优化总结前言代码优化,一个很重要的课题.可能有些人觉得没用,一些细小的地方有什么好修改的,改与不改对于代码的运行效率有什么影响呢?这个问题我是这么考虑的,就像大海里面的 ...

  8. Jboss未授权访问漏洞复现

    一.前言 漏洞原因:在低版本中,默认可以访问Jboss web控制台(http://127.0.0.1:8080/jmx-console),无需用户名和密码. 二.环境配置 使用docker搭建环境 ...

  9. AngularJS 路由和模板实例及路由地址简化方法

    最近一同事在学习AngularJS,在路由与模板的学习过程中遇到了一些问题,于是今天给她写了个例子,顺便分享出来给那些正在学习AngularJS的小伙伴们. 话说这AngularJs 开发项目非常的爽 ...

  10. java获取一天前的时间

    获取一天前的时间 Date date = new Date(); Calendar calendar = Calendar.getInstance(); calendar.setTime(date); ...