Redis全局ID生成器的实现


Posted in Redis onJune 05, 2022

全局ID生成器,是一种在分布式系统下用来生成全局唯一ID的工具,一般满足下列特性:

  • 唯一性:确保ID是唯一的,不可重复
  • 递增性:确保是整体逐渐增大的,这样有利于数据库创建索引
  • 安全性:ID的规律性不是特别的明显,防止根据ID号猜测其他的ID,确保安全性
  • 高性能:确保生成ID的速度足够快
  • 高可用:确保任何时候都能用

实现原理:

为了增加ID的安全性,可以不直接使用Redis自增的数值,而是拼接一些其他的信息,ID的组成如下图:

Redis全局ID生成器的实现

  • 符号位:1bit,永远为0,表示正数
  •  时间戳:31bit,以秒为单位,可以使用大约69年
  •  序列号:32bit,相同秒数的情况下,ID在序列号位置上增加,支持每秒产生2^32个不同的ID

代码实现:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
 
@Component
public class RedisIdWorker {
 
    /**
     * 开始时间戳 (2022-01-01 00:00:00)
     */
    private static final long BEGIN_TIMESTAMP = 1640995200L;
 
    /**
     * 序列号的位数
     */
    private static final int COUNT_BITS = 32;
 
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
 
    /**
     * 生成ID
     *
     * @param keyPrefix 业务系统的前缀
     * @return ID
     */
    public long nextId(String keyPrefix) {
        // 生成时间戳
        long timestamp = LocalDateTime.now().toEpochSecond(ZoneOffset.UTC) - BEGIN_TIMESTAMP;
        // 生成序列号
        String key = "icr:" + keyPrefix + ":" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy:MM:dd"));
        long count = stringRedisTemplate.opsForValue().increment(key);
        // 拼接并返回
        return timestamp << COUNT_BITS | count;
    }
 
    /**
     * 获取时间戳 (2022-01-01 00:00:00)
     * @param args
     */
    public static void main(String[] args) {
        LocalDateTime time = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
        long second = time.toEpochSecond(ZoneOffset.UTC);
        System.out.println(second);
    }
}

生成序号:

Redis的自增是有上限的,最大值为2^64。虽然这个数是很大了,但是毕竟还有会有上限,时间足够长还是有可能超过这个数的。所以即使是同一个业务,也不能使用同一个key。因此可以在key中增加日期,比如:icr:业务名:2022:05:14。这样的话每天都会是新的key,每天的自增量不可能超过2^64,所以这样的key是比较合适的选择。

到此这篇关于Redis全局ID生成器的实现的文章就介绍到这了,更多相关Redis全局ID生成器内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Redis 相关文章推荐
浅谈Redis位图(Bitmap)及Redis二进制中的问题
Jul 15 Redis
SpringBoot整合Redis入门之缓存数据的方法
Nov 17 Redis
分布式架构Redis中有哪些数据结构及底层实现原理
Mar 13 Redis
Redis 中使用 list,streams,pub/sub 几种方式实现消息队列的问题
Mar 16 Redis
windows安装 redis 6.2.6最新步骤详解
Apr 26 Redis
Redis 限流器
May 15 Redis
Redis keys命令的具体使用
Jun 05 Redis
Redis实现分布式锁的五种方法详解
Jun 14 Redis
python中使用redis用法详解
Dec 24 Redis
Redis实战之Lettuce的使用技巧详解
Dec 24 Redis
Redis keys命令的具体使用
Jun 05 #Redis
Redis入门基础常用操作命令整理
Jun 01 #Redis
Redis基本数据类型String常用操作命令
Jun 01 #Redis
Redis基本数据类型List常用操作命令
Jun 01 #Redis
Redis基本数据类型Set常用操作命令
Jun 01 #Redis
Redis基本数据类型哈希Hash常用操作命令
Jun 01 #Redis
Redis基本数据类型Zset有序集合常用操作
Jun 01 #Redis
You might like
php smarty模版引擎中变量操作符及使用方法
2009/12/11 PHP
使用php清除bom示例
2014/03/03 PHP
PHP编程中的__clone()方法使用详解
2015/11/27 PHP
php数组函数array_walk用法示例
2016/05/26 PHP
PHP实现提取多维数组指定一列的方法总结
2019/12/04 PHP
javascript学习笔记(四) Number 数字类型
2012/06/19 Javascript
鼠标悬浮显示二级菜单效果的jquery实现
2014/10/29 Javascript
javascript框架设计读书笔记之数组的扩展与修复
2014/12/02 Javascript
jQuery插件扩展测试实例
2016/06/21 Javascript
详谈JavaScript的闭包及应用
2017/01/17 Javascript
Spring shiro + bootstrap + jquery.validate 实现登录、注册功能
2017/06/02 jQuery
JavaScript设计模式之构造函数模式实例教程
2018/07/02 Javascript
vue中过滤器filter的讲解
2019/01/21 Javascript
微信小程序实现多选框全选与取消全选功能示例
2019/05/14 Javascript
JS中的一些常用的函数式编程术语
2019/06/15 Javascript
[46:20]CHAOS vs Alliacne 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/16 DOTA
[38:42]完美世界DOTA2联赛循环赛 Matador vs Forest BO2第二场 11.05
2020/11/05 DOTA
跟老齐学Python之Python安装
2014/09/12 Python
对numpy中数组元素的统一赋值实例
2018/04/04 Python
详解python 注释、变量、类型
2018/08/10 Python
Django 开发环境与生产环境的区分详解
2019/07/26 Python
python 初始化一个定长的数组实例
2019/12/02 Python
python_mask_array的用法
2020/02/18 Python
Python sklearn中的.fit与.predict的用法说明
2020/06/28 Python
Python如何将将模块分割成多个文件
2020/08/04 Python
英国标志性生活方式品牌:Skinnydip London
2019/12/15 全球购物
几个常见的软件测试问题
2016/09/07 面试题
中学生个人自我评价
2014/02/06 职场文书
党员公开承诺书
2014/03/25 职场文书
班长竞选演讲稿
2014/04/24 职场文书
初中优秀学生评语
2014/12/29 职场文书
2015年推广普通话演讲稿
2015/03/20 职场文书
婚宴父母致辞
2015/07/27 职场文书
导游词之藏龙百瀑景区
2019/12/30 职场文书
Golang 如何实现函数的任意类型传参
2021/04/29 Golang
船舶调度指挥系统——助力智慧海事
2022/02/18 无线电