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配置文件中常用配置详解
Apr 14 Redis
详解Redis实现限流的三种方式
Apr 27 Redis
详解redis分布式锁的这些坑
May 19 Redis
解析Redis Cluster原理
Jun 21 Redis
Redis缓存-序列化对象存储乱码问题的解决
Jun 21 Redis
浅谈Redis中的RDB快照
Jun 29 Redis
使用Redis实现实时排行榜功能
Jul 02 Redis
在项目中使用redis做缓存的一些思路
Sep 14 Redis
Redis高并发防止秒杀超卖实战源码解决方案
Nov 01 Redis
redis中lua脚本使用教程
Nov 01 Redis
Redis官方可视化工具RedisInsight安装使用教程
Apr 19 Redis
Redis基本数据类型Set常用操作命令
Jun 01 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 文件上传功能实现代码
2009/06/24 PHP
php命令行用法入门实例教程
2014/10/27 PHP
轻轻松松学习JavaScript
2007/02/25 Javascript
js DOM 元素ID就是全局变量
2012/09/20 Javascript
JavaScript显示当然日期和时间即年月日星期和时间
2013/10/29 Javascript
实例分析js和C#中使用正则表达式匹配a标签
2014/11/26 Javascript
jQuery序列化表单成对象的简单实现
2016/11/29 Javascript
JS基于正则截取替换特定字符之间字符串操作示例
2017/02/03 Javascript
Vue导出json数据到Excel电子表格的示例
2017/12/04 Javascript
详解使用React进行组件库开发
2018/02/06 Javascript
浅谈Webpack打包优化技巧
2018/06/12 Javascript
python登录QQ邮箱发信的实现代码
2013/02/10 Python
用smtplib和email封装python发送邮件模块类分享
2014/02/17 Python
python迭代器实例简析
2014/09/25 Python
Windows下搭建python开发环境详细步骤
2020/07/20 Python
教你学会使用Python正则表达式
2017/09/07 Python
pytorch对可变长度序列的处理方法详解
2018/12/08 Python
python绘制评估优化算法性能的测试函数
2019/06/25 Python
python实现电子书翻页小程序
2019/07/23 Python
python实现身份证实名认证的方法实例
2019/11/08 Python
浅谈Python type的使用
2019/11/19 Python
python实现12306登录并保存cookie的方法示例
2019/12/17 Python
快速查找Python安装路径方法
2020/02/06 Python
读取nii或nii.gz文件中的信息即输出图像操作
2020/07/01 Python
Python + opencv对拍照得到的图片进行背景去除的实现方法
2020/11/18 Python
用HTML5制作视频拼图的教程
2015/05/13 HTML / CSS
大学毕业的自我鉴定
2013/10/08 职场文书
日语求职信范文
2013/12/17 职场文书
人事部主管岗位职责
2013/12/26 职场文书
小学生评语集锦
2014/04/18 职场文书
涉密人员保密承诺书
2014/05/28 职场文书
老员工辞职信范文
2015/05/12 职场文书
迎新年主持词
2015/07/06 职场文书
正确使用MySQL update语句
2021/05/26 MySQL
教你用Python爬取英雄联盟皮肤原画
2021/06/13 Python
如何利用React实现图片识别App
2022/02/18 Javascript