本篇分享内容是关于生成分布式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. 开发一个Spring Boot Starter!

    在上一篇文章中,我们已经了解了一个starter实现自动配置的基本流程,在这一小结我们将复现上一过程,实现一个自定义的starter. 先来分析starter的需求: 在项目中添加自定义的starte ...

  2. 关于http 500错误的小结分享

    一般情况下,http 500内部服务器(HTTP-Internal Server Error)错误说明IIS服务器无法解析ASP代码,访问一个静态页面试试是否也出现这个问题. 如果访问静态页面没问题, ...

  3. Activiti 开发案例之动态指派任务

    流程图 以上是一个请假的流程图,以下为流程任务节点描述: 员工发起请假流程 部门经理审批 同意则进入人事审批 拒绝则调整申请或者直接结束流程 人事审批通过则进入销假环节 人事审批拒绝则调整申请或者直接 ...

  4. 对已经存在的hbase表修改压缩方式

    业务上可能会遇到这种情况,在最初创建hbase表时候,未指定压缩方式,当数据导入之后,由rowkey带来的数据膨胀导致hdfs上的数据大小远远大于原始数据大小.所以这时候可能就不得不考虑使用压缩,但是 ...

  5. static用法总结:

    这是我的第一篇随笔! 1.当1.cpp和2.cpp都定义了同一个全局时链接会报错,变量名冲突.需要将其中一个设置为static控制其作用域为只在一个源文件内部. 2.函数名也是全局的,故static的 ...

  6. Log2Net的部署和运维

    前面几节中,笔者介绍了Log2Net组件的方方面面.但是,有人说,我用不起来,各种头疼的小问题.下面,我们就具体的看一看要怎么把这个组件应用到实际的项目中吧. 一.Log2Net组件的发布 前文中,我 ...

  7. Python|队列Queue

    一 前言 本文算是一次队列的学习笔记,Queue 模块实现了三种类型的队列,它们的区别仅仅是队列中元素被取回的顺序.在 FIFO 队列中,先添加的任务先取回.在 LIFO 队列中,最近被添加的元素先取 ...

  8. Asp.NetCore源码学习[1-2]:配置[Option]

    Asp.NetCore源码学习[1-2]:配置[Option] 在上一篇文章中,我们知道了可以通过IConfiguration访问到注入的ConfigurationRoot,但是这样只能通过索引器IC ...

  9. Kafka集群环境配置

    Kafka集群环境配置 1 环境准备 1.1 集群规划 Node02 Node03 Node04 zk zk zk kafka kafka kafka 1.2 jar包下载 安装包:kafka_2.1 ...

  10. pip安装ansible的过程

    我的python环境已经搭好了pip,可以用pip直接安装. 1.首先要安装基础环境: 1)yum install gcc glibc-devel zlib-devel rpm-build opens ...