redis生成分布式id方案
分布式Id - redis方式
本篇分享内容是关于生成分布式Id的其中之一方案,除了redis方案之外还有如:数据库,雪花算法,mogodb(object_id也是数据库)等方案,对于redis来说是我们常用并接触比较多的,因此主要谈谈结合redis生成分布式id方案。
- 分布式Id设计流程图
- 基于redis的hash自动increment累加生成有序Id
- 定期删除无用hash列
分布式Id设计流程图(有点粗略)
基于redis的hash自动increment累加生成有序Id
使用redis方案生成id,其中之一的方式主要使用increment(递增),不管是string、hash等都具有该方法,为了更方便管理我们id生成key这里建议使用hash的列的方式,以下内容都基于springboot分享;
当然,第一步我们需要创建一个hash和hkey才行,至于在业务第一次被访问来创建这个hash还是通过服务自动创建这个看业务和流量,这里的hkey是有一定规则的(当然不用局限性),这里我按照日期格式来做key,可以有如下代码:

1 /**
2 * 生成每天的初始Id
3 * @param hashName
4 * @return
5 */
6 public String initPrimaryId(String hashName) {
7 Assert.hasLength(hashName, "hashName不能为空");
8
9 String hashCol = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
10 //自定义编号规则
11 String hashColVal = hashCol + "00001";
12 redisTemplate.opsForHash().putIfAbsent(hashName, hashCol, hashColVal);
13 return hashCol;
14 }

上面很容易理解,hash中key是有每天日期格式组成,意思每天都需要生成一个新的日期key,通过putIfAbsent达到不重复添加的原则,至于hval可以根据自定义编号规则来生成一串数字字符(注:一定要数字);有了上面的基础,我们仅仅需要increment来累加,redis即帮我们完整hval+1的操作,当然可以自定义累加数,如下代码:

1 /**
2 * 获取分布式Id
3 *
4 * @param hashName
5 * @return
6 */
7 public long getPrimaryId(String hashName) {
8 try {
9 String hashCol = initPrimaryId(hashName);
10 return redisTemplate.opsForHash().increment(hashName, hashCol, 1);
11 } catch (Exception ex) {
12 ex.printStackTrace();
13 }
14 return 0;
15 }

定期删除无用hash列
就上面我们通过hash来设置每天id只增初始值,hash的hkey布局用自动过期功能,因此我们需要代码中维护一套清除来hkey的机制,既然id是根据日期生成,我们可以就用往前推n天的方式达到清除老hkey目的:

1 /**
2 * 删除多少天之前的cols
3 * @param hashName
4 * @param lessDay
5 * @return
6 */
7 public Long removePrimaryByLessDay(String hashName, int lessDay) {
8 try {
9 //当前日期
10 String hashCol = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
11 long idl = Long.valueOf(hashCol) - lessDay;
12
13 String[] removeCols = redisTemplate.opsForHash().entries(hashName).keySet().stream().
14 map(key -> key.toString()).
15 filter(key -> idl > Long.valueOf(key)). //从+1开始,避免删除当天数据
16 toArray(String[]::new);
17
18 if (ArrayUtils.isNotEmpty(removeCols)) {
19 return redisTemplate.opsForHash().delete(hashName, removeCols);
20 }
21 } catch (Exception ex) {
22 ex.printStackTrace();
23 }
24 return 0L;
25 }

按照日期来生成分布式id,达到id不重复的目的,这也就是分布式id(不重复),看起来简单其实如果在高流量冲击下,需要考虑的东西要很多,比如:什么时候生成初始Id、在多个服务器保证服务器时间尽可能一样情况下,该保留多少日期hkey等;
就上面代码对初始Id就做的不是很好,在业务获取Id时候,会去检测并创建id,这样与redis交互就多了一次,通常可以用服务来一次性生成当前日期往后推n天的hkey,这样就避免了在业务获取id时候,还要去putIfAbsent一次验证,减少了请求次数。实在不行可以使用lua脚本放在一次请求去做put和increment,你可能会用到:
1 RedisScript script = new DefaultRedisScript("");
2 redisTemplate.execute(script, Arrays.asList(""));
redis生成分布式id方案的更多相关文章
- 大型互联网公司分布式ID方案总结
ID是数据的唯一标识,传统的做法是利用UUID和数据库的自增ID,在互联网企业中,大部分公司使用的都是Mysql,并且因为需要事务支持,所以通常会使用Innodb存储引擎,UUID太长以及无序,所以并 ...
- 基于redis的分布式ID生成器
基于redis的分布式ID生成器
- 雪花算法生成分布式ID
分布式主键ID生成方案 分布式主键ID的生成方案有以下几种: 数据库自增主键 缺点: 导入旧数据时,可能会ID重复,导致导入失败 分布式架构,多个Mysql实例可能会导致ID重复 UUID 缺点: 占 ...
- 分布式ID方案有哪些以及各自的优劣势,我们当如何选择
作者介绍 段同海,就职于达达基础架构团队,主要参与达达分布式ID生成系统,日志采集系统等中间件研发工作. 背景 在分布式系统中,经常需要对大量的数据.消息.http请求等进行唯一标识,例如:在分布式系 ...
- 分布式ID系列之为什么需要分布式ID以及生成分布式ID的业务需求
为什么需要分布式id生成系统 在复杂分布式系统中,往往需要对大量的数据和消息进行唯一标识.如在美团点评的金融.支付.餐饮.酒店.猫眼电影等产品的系统中,数据日渐增长,对数据分库分表后需要有一个唯一ID ...
- 分布式ID方案SnowFlake雪花算法分析
1.算法 SnowFlake算法生成的数据组成结构如下: 在java中用long类型标识,共64位(每部分用-分开): 0 - 0000000000 0000000000 0000000000 000 ...
- 基于雪花算法生成分布式ID(Java版)
SnowFlake算法原理介绍 在分布式系统中会将一个业务的系统部署到多台服务器上,用户随机访问其中一台,而之所以引入分布式系统就是为了让整个系统能够承载更大的访问量.诸如订单号这些我们需要它是全局唯 ...
- 基于 Redis 生成分布式订单号
环境依赖: //spingBoot <version>2.6.6</version> //jdk11 <dependency> <groupId>org ...
- [Node.js] Node + Redis 实现分布式Session方案
原文地址: http://www.moye.me/?p=565 Session是什么? Session 是面向连接的状态信息,是对 Http 无状态协议的补充. Session 怎么工作? Sessi ...
随机推荐
- 在ASP.NET Web API 2中使用Owin基于Token令牌的身份验证
基于令牌的身份验证 基于令牌的身份验证主要区别于以前常用的常用的基于cookie的身份验证,基于cookie的身份验证在B/S架构中使用比较多,但是在Web Api中因其特殊性,基于cookie的身份 ...
- Java内功心法,创建型设计模式包括哪些
1. 单例(Singleton) Intent 确保一个类只有一个实例,并提供该实例的全局访问点. Class Diagram 使用一个私有构造函数.一个私有静态变量以及一个公有静态函数来实现. 私有 ...
- 浅聊几种主流Docker网络的实现原理
原文:https://mp.weixin.qq.com/s/Jdxct8qHrBUtkUq-hnxSRw 参考:https://blog.csdn.net/yarntime/article/detai ...
- Python学习笔记之将数据写入到文件中
10-3 访客:编写一个程序,提示用户输入其名字:用户作出响应后,将其名字写入到文件guest.txt 中. 编写Python代码: username = input("Please ent ...
- vue-cli随机生成port源码
const portfinder = require('portfinder'): const port = await portfinder.getPortPromise(): 两行代码 端口搜索范 ...
- Risc-V简要概括
1.Risc-V硬件平台术语 一个RiscV硬件平台可以包含一个或多个RiscV兼容的核心.其它非RiscV兼容的核心.固定功能的加速器.各种物理存储器结构.I/O设备以及允许这些部件相互连通的互联结 ...
- Java集合学习(10):hashcode() 和 equals()方法
哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: public native int hashCode(); 根据这个 ...
- IDEA Mac 快捷键
智能提示 ⌘ -> command ⇧ -> shift ⌥ -> option ⬆ -> 上箭头 ⬇ -> 下箭头 ⌃ -> Control 编辑 快捷键 说明 ...
- mongo连接不上Timed out after 30000
本地连接mongo报错,错误代码为: Caused by: com.mongodb.MongoTimeoutException: Timed out after 30000 ms while wait ...
- windows server 2012配置php环境教程
买了windows系统的服务器(VPS)等之后我们需要一个php环境来搭建自己的项目,这里介绍手工在windows server 2012上面配置php环境的具体步骤,适合使用服务器和VPS等的新手. ...