本篇分享内容是关于生成分布式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目的:

复制代码