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缓存在项目中的使用
May 20 Redis
Java Socket实现Redis客户端的详细说明
May 26 Redis
聊聊redis-dump工具安装问题
Jan 18 Redis
Redis调用Lua脚本及使用场景快速掌握
Mar 16 Redis
Redis集群节点通信过程/原理流程分析
Mar 18 Redis
在Centos 8.0中安装Redis服务器的教程详解
Mar 21 Redis
详解Redis的三种常用的缓存读写策略步骤
May 06 Redis
解决 redis 无法远程连接
May 15 Redis
Redis基本数据类型String常用操作命令
Jun 01 Redis
Redis入门基础常用操作命令整理
Jun 01 Redis
如何使用注解方式实现 Redis 分布式锁
Jul 23 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
世界上第一台立体声收音机
2021/03/01 无线电
短波收音机简介
2021/03/01 无线电
社区(php&amp;&amp;mysql)一
2006/10/09 PHP
php采用curl模仿登录人人网发布动态的方法
2014/11/07 PHP
PHP递归实现层级树状展开
2016/04/01 PHP
JavaScript 字符串连接性能优化
2008/12/20 Javascript
Javascript继承机制的设计思想分享
2011/08/28 Javascript
Node.js中的缓冲与流模块详细介绍
2015/02/11 Javascript
使用jquery获取url及url参数的简单实例
2016/06/14 Javascript
H5移动端图片压缩上传开发流程
2016/11/09 Javascript
jQuery如何跳转到另一个网页 就这么简单
2016/12/28 Javascript
微信小程序-横向滑动scroll-view隐藏滚动条
2017/04/20 Javascript
jquery ui sortable拖拽后保存位置
2017/04/27 jQuery
axios中cookie跨域及相关配置示例详解
2017/12/20 Javascript
Vue页面骨架屏的实现方法
2018/05/22 Javascript
在小程序开发中使用npm的方法
2018/10/17 Javascript
webpack打包非模块化js的方法
2018/10/24 Javascript
angularjs通过过滤器返回超链接的方法
2018/10/26 Javascript
基于vue2.0实现仿百度前端分页效果附实现代码
2018/10/30 Javascript
vue+webpack dev本地调试全局样式引用失效的解决方案
2019/11/12 Javascript
详解Python中类的定义与使用
2017/04/11 Python
python主线程捕获子线程的方法
2018/06/17 Python
Python/Django后端使用PIL Image生成头像缩略图
2019/04/30 Python
德国知名健康零食网上商店:Seeberger
2017/07/27 全球购物
EMU Australia澳大利亚官网:澳大利亚本土雪地靴品牌
2019/07/24 全球购物
TobyDeals美国:在电子产品上获得最好的优惠和折扣
2019/08/11 全球购物
C#怎么让一个窗口居中显示?
2015/10/20 面试题
vue 中 get / delete 传递数组参数方法
2021/03/23 Vue.js
护理专科毕业推荐信
2013/11/10 职场文书
就职演讲稿范文
2014/05/19 职场文书
安全生产月标语
2014/10/07 职场文书
学校捐款活动总结
2015/05/09 职场文书
开场白怎么写
2015/06/01 职场文书
2015年社区重阳节活动总结
2015/07/30 职场文书
Python机器学习之决策树和随机森林
2021/07/15 Javascript
table不让td文字溢出操作方法
2022/12/24 HTML / CSS