本篇分享内容是关于生成分布式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,可以有如下代码:

     /**
* 生成每天的初始Id
* @param hashName
* @return
*/
public String initPrimaryId(String hashName) {
Assert.hasLength(hashName, "hashName不能为空"); String hashCol = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
//自定义编号规则
String hashColVal = hashCol + "";
redisTemplate.opsForHash().putIfAbsent(hashName, hashCol, hashColVal);
return hashCol;
}

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

     /**
* 获取分布式Id
*
* @param hashName
* @return
*/
public long getPrimaryId(String hashName) {
try {
String hashCol = initPrimaryId(hashName);
return redisTemplate.opsForHash().increment(hashName, hashCol, );
} catch (Exception ex) {
ex.printStackTrace();
}
return ;
}

定期删除无用hash列

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

     /**
* 删除多少天之前的cols
* @param hashName
* @param lessDay
* @return
*/
public Long removePrimaryByLessDay(String hashName, int lessDay) {
try {
//当前日期
String hashCol = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
long idl = Long.valueOf(hashCol) - lessDay; String[] removeCols = redisTemplate.opsForHash().entries(hashName).keySet().stream().
map(key -> key.toString()).
filter(key -> idl > Long.valueOf(key)). //从+1开始,避免删除当天数据
toArray(String[]::new); if (ArrayUtils.isNotEmpty(removeCols)) {
return redisTemplate.opsForHash().delete(hashName, removeCols);
}
} catch (Exception ex) {
ex.printStackTrace();
}
return 0L;
}

按照日期来生成分布式id,达到id不重复的目的,这也就是分布式id(不重复),看起来简单其实如果在高流量冲击下,需要考虑的东西要很多,比如:什么时候生成初始Id、在多个服务器保证服务器时间尽可能一样情况下,该保留多少日期hkey等;

就上面代码对初始Id就做的不是很好,在业务获取Id时候,会去检测并创建id,这样与redis交互就多了一次,通常可以用服务来一次性生成当前日期往后推n天的hkey,这样就避免了在业务获取id时候,还要去putIfAbsent一次验证,减少了请求次数。实在不行可以使用lua脚本放在一次请求去做put和increment,你可能会用到:

             RedisScript script = new DefaultRedisScript("");
redisTemplate.execute(script, Arrays.asList(""));

分布式Id - redis方式的更多相关文章

  1. 分布式id 实现方式

    1. uuid 2. twitter的Snowflake 3. MongoDB ObjectID 4. Ticket Server 5. Instagram采用的方式(UUID方式)

  2. redis生成分布式id方案

    分布式Id - redis方式   本篇分享内容是关于生成分布式Id的其中之一方案,除了redis方案之外还有如:数据库,雪花算法,mogodb(object_id也是数据库)等方案,对于redis来 ...

  3. 一口气说出 9种 分布式ID生成方式,面试官有点懵了

    整理了一些Java方面的架构.面试资料(微服务.集群.分布式.中间件等),有需要的小伙伴可以关注公众号[程序员内点事],无套路自行领取 本文作者:程序员内点事 原文链接:https://mp.weix ...

  4. 分布式 ID 的 9 种生成方式

    为什么要用分布式ID? 在说分布式ID的具体实现之前,我们来简单分析一下为什么用分布式ID?分布式ID应该满足哪些特征? 什么是分布式ID? 拿MySQL数据库举个栗子: 在我们业务数据量不大的时候, ...

  5. 一口气说出9种分布式ID生成方式,面试官有点懵

    一.为什么要用分布式ID? 在说分布式ID的具体实现之前,我们来简单分析一下为什么用分布式ID?分布式ID应该满足哪些特征? 1.1.什么是分布式ID? 拿MySQL数据库举个栗子:在我们业务数据量不 ...

  6. 听说:分布式ID不能全局递增?

    大家好,我是[架构摆渡人],一只十年的程序猿.这是实践经验系列的第十一篇文章,这个系列会给大家分享很多在实际工作中有用的经验,如果有收获,还请分享给更多的朋友. 前面有篇文章我们讲到用时间来代替自增I ...

  7. Redis系列(二)--分布式锁、分布式ID简单实现及思路

    分布式锁: Redis可以实现分布式锁,只是讨论Redis的实现思路,而真的实现分布式锁,Zookeeper更加可靠 为什么使用分布式锁: 单机环境下只存在多线程,通过同步操作就可以实现对并发环境的安 ...

  8. 分布式ID系列(4)——Redis集群实现的分布式ID适合做分布式ID吗

    首先是项目地址: https://github.com/maqiankun/distributed-id-redis-generator 关于Redis集群生成分布式ID,这里要先了解redis使用l ...

  9. 基于redis的分布式ID生成器

    基于redis的分布式ID生成器  

随机推荐

  1. thinkphp3.2集成极光推送

    项目中用到了给客户端的推送功能,选用了极光推送,下面演示一下在thinkphp中集成极光推送 1.下载极光推送的php类,可以从笔者的git下载 地址:https://git.oschina.net/ ...

  2. Selenium+java - 借助autolt完成上传文件操作

    写在前面: 上传文件是每个自动化测试同学会遇到,而且可以说是面试必考的问题,标准控件我们一般用sendkeys()就能完成上传,但是我们的测试网站的上传控件一般为自己封装的,用传统的上传已经不好用了, ...

  3. gdb调试和编译后运行结果不一致

    今天在看代码时,遇到这么一段代码,我但是用g++编译了,运行发现有Segmentation fault. 然后就用gdb跟进去看看,可是gdb却正常执行了.不知道什么原因. #include < ...

  4. JAVA基础知识(六)Java 静态多分派&动态单分派

    1.分派发生在编译期和运行期,编译期的分派为静态分派,运行期的为动态分派. 2.编译期是根据对象声明的类型来选择方法,运行期是根据对象实际类型来选择方法. 3.单分派和多分派取决于宗量, 方法调用者和 ...

  5. LeetCode——372. Super Pow

    题目链接:https://leetcode.com/problems/super-pow/description/ Your task is to calculate ab mod 1337 wher ...

  6. Java——集合类

    1.容器的打印 import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import jav ...

  7. 面试java后端面经_3

    小姐姐说:你一点都不懂表达,一点都不懂爱情,一点也不爱我! 你答:你知道吗,我听说过一个这样的故事,讲的就是有一个小女孩和一个男孩在一起,小男孩呢很不幸是位聋哑人,虽然如此,但是他们的日子过得特别的美 ...

  8. .net软件日常开发规范-基本标准

    一. 基本标准 代码和SQL脚本均不要出现无意义的空格和空行. 所有SQL脚本确保可以重复运行不出错,添加数据的脚本重复运行不会重复添加数据. 能用一行代码或脚本解决的不要写出两行,能用一个方法解决的 ...

  9. windows如何访问wsl系统下的文件

    windows如何访问wsl系统下的文件 可以在wsl终端输入以下命令 explorer.exe . 会出现如下界面 这样就可以很方便的查看wsl的文件了

  10. spring-boot-plus V1.2.1 发布 文件上传下载和静态资源访问

    [V1.2.1-RELEASE] 2019.08.21 ⭐️ New Features 文件上传保存到服务器指定目录 文件下载 访问上传的图片等资源 启用项目静态资源访问,可访问static/temp ...