本篇分享内容是关于生成分布式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(""));

最新文章

  1. Git for Windows - The Program can't start because libiconv2.dll is missing
  2. 【linux】nohup运行守护进程
  3. 奇怪吸引子---Sakarya
  4. java中时间的比较
  5. Win7+VMware Workstation环境下的CentOS-Linux网络连接设置
  6. 在dom4j中使用XPath
  7. HDU 2669 Romantic(扩展欧几里德, 数学题)
  8. 51nod1079中国剩余定理
  9. 生成Excel錯誤 遠端程序呼叫失敗。 (發生例外狀況於 HRESULT: 0x800706BE)
  10. 部分实用的SQL语句
  11. Hadoop-Yarn-HA集群搭建(搭建篇)
  12. Android 短信模块分析(三) MMS入口分析
  13. Ubuntu16.04安装NVIDIA驱动时的一些坑与解决方案
  14. UITableView的性能优化1
  15. Android Studio教程09-加载器Loader的使用
  16. Linux软件包管理之yum在线管理
  17. python与java的猜拳游戏
  18. RSEG用法和汇编问号的涵义
  19. 利用PCA进行故障监测
  20. Centos 7上安装Elasticsearch

热门文章

  1. 算法与数据结构基础 - 回溯(Backtracking)
  2. IDEA+maven搭建scala开发环境(spark)(半转载)
  3. java 购物商城小项目训练
  4. ES 26 - 通过partial update局部更新索引文档 (partial update增量修改原理)
  5. H5中的history方法Api介绍
  6. 洛谷 P2044 [NOI2012]随机数生成器
  7. 调用百度翻译 API 来翻译网站信息
  8. 004——Netty之高性能IO(Reactor)
  9. Spring aop注解失效
  10. 消息中间件——RabbitMQ(二)各大主流消息中间件综合对比介绍!