本篇分享内容是关于生成分布式Id的其中之一方案,除了redis方案以外还有如:数据库,雪花算法,mogodb(object_id也是数据库)等方案,对于redis来讲是咱们经常使用并接触比较多的,所以主要谈谈结合redis生成分布式id方案。redis
使用redis方案生成id,其中之一的方式主要使用increment(递增),无论是string、hash等都具备该方法,为了更方便管理咱们id生成key这里建议使用hash的列的方式,如下内容都基于springboot分享;算法
固然,第一步咱们须要建立一个hash和hkey才行,至于在业务第一次被访问来建立这个hash仍是经过服务自动建立这个看业务和流量,这里的hkey是有必定规则的(固然不用局限性),这里我按照日期格式来作key,能够有以下代码:spring
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来设置天天id只增初始值,hash的hkey布局用自动过时功能,所以咱们须要代码中维护一套清除来hkey的机制,既然id是根据日期生成,咱们能够就用往前推n天的方式达到清除老hkey目的:springboot
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,你可能会用到:less
1 RedisScript script = new DefaultRedisScript(""); 2 redisTemplate.execute(script, Arrays.asList(""));