基于Redis实现全局唯一Id

 微信公众号访问地址:基于Redis实现全局唯一Id

推荐文章:

    1、使用原生Redis命令实现分布式锁

​    2、为什么引入Redisson分布式锁?

    3、SpringBoot整合多数据源,并支持动态新增与切换(详细教程)

    4、SpringBoot统一标准响应格式及异常处理

   5、SpringBoot用线程池ThreadPoolTaskExecutor异步处理百万级数据

一、简介

使用数据库自增ID就存在一些问题:

    1、受单表自增数量的限制;

      原因:mysql单表的容量不宜超过500W条,数据量过大之后,就需要进行拆库拆表,但拆分表之后,它们从逻辑上讲仍然是同一张表,所以他们的id是不能一样的(不同表,若使用自增ID,是可能一样的),所以随着我们的业务数据越来越大,我们需要保证id的唯一性。

    2、id的规律性太明显。

      原因:自增id具有太明显的规则,用户或者说商业对手很容易猜测出来一些敏感信息,例如:在一天时间内,我们卖出了多少单,这明显不合适。

二、全局唯一ID生成策略

      一般要满足下列特性:

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

组成说明:

    1、符号位:1bit,永远为0;

    2、时间戳(31 Bit):31bit,以秒为单位,可以使用69年;

    3、序列号:32bit,秒内的计数器,支持每秒产生2^32个不同ID。

三、基于Redis实现全局唯一Id案例

    原理:基于Redis 的INCR 命令生成分布式全局唯一id。INCR 命令主要有以下2个特征:

      1、具备了“INCR AND GET”的原子操作,即:增加并返回结果的原子操作。这个原子性很方便我们实现获取ID。

      2、Redis是单进程单线程架构,INCR命令不会出现id重复。

3.1、构建RedisIdUtils类

/*** 功能描述:使用redis生成全局唯一ID* @Author: yyalin* @CreateDate: 2023/8/13 11:35*/
@Component
public class RedisIdUtils {//预生成开始时间戳private static final long BEGIN_TIMESTAMP = 1640995200L;//序列号的位数private static final int COUNT_BITS = 32;//redis提供的字符串private StringRedisTemplate stringRedisTemplate;//有参构造函数public RedisIdUtils(StringRedisTemplate stringRedisTemplate) {this.stringRedisTemplate = stringRedisTemplate;}/*** 功能描述:根据keyPrefix前缀生成对应业务的全局唯一ID* @MethodName: nextId* @MethodParam: [keyPrefix:使用前缀来区分不同的业务]* @Return: long* @Author: yyalin* @CreateDate: 2023/8/13 12:20*/public long nextId(String keyPrefix) {// 1.生成时间戳LocalDateTime now = LocalDateTime.now();long nowSecond = now.toEpochSecond(ZoneOffset.UTC);long timestamp = nowSecond - BEGIN_TIMESTAMP;// 2.生成序列号// 2.1.获取当前日期,精确到天String date = now.format(DateTimeFormatter.ofPattern("yyyy:MM:dd"));// 2.2.自增长 icr:order:2023:08:13long count = stringRedisTemplate.opsForValue().increment("icr:" + keyPrefix + ":" + date);// 3.拼接并返回  timestamp << COUNT_BITS :向左移动32位//原本时间戳在低位上,通过向左移动32位,变位到高位存储,低32位都是0,然后与自增序列按位操作//形成低32位为序列号。return timestamp << COUNT_BITS | count;}
}

3.2、构建多线程测试类

** * @Description: TODO:测试RedisIdUtils * @Author: yyalin * @CreateDate: 2023/8/13 12:27 * @Version: V1.0 */@Service@Slf4jpublic class TestRedisIdUtils {    @Autowired    private RedisIdUtils redisIdUtils;    //使用自定义的线程池    private ExecutorService executorService = Executors.newFixedThreadPool(500);    /**     * 功能描述:使用多线程测试生成40000条数据耗时     * @MethodName: testIdWorker     * @MethodParam: [nums]     * @Return: void     * @Author: yyalin     * @CreateDate: 2023/8/13 12:36     */    public void testIdWorker(int nums) throws InterruptedException {        //同步协调在多线程的等待于唤醒问题 分线程全部走完之后,主线程再走        CountDownLatch latch = new CountDownLatch(nums);        Runnable task = () -> {            for (int i = 0; i < 100; i++) {                long id = redisIdUtils.nextId("order");                System.out.println("id = " + id);            }            latch.countDown();        };        long begin = System.currentTimeMillis();        for (int i = 0; i < nums; i++) {            executorService.submit(task);        }        //阻塞方法 让main线程阻塞        latch.await();        long end = System.currentTimeMillis();        log.info("生成"+nums*100+"条id共计耗时(毫秒) = " + (end - begin));    }}

3.3、测试结果

序列
 
线程数条数耗时(秒)
1500300000.781
2500400000.993
3500500001.164

      总结:从测试结果不难看出,基于redis实现全局唯一ID,性能还是非常高的,并且耗时非常短的。

更多优秀文章,请关注个人微信公众号或搜索“程序猿小杨”查阅。

参考文章:

https://blog.csdn.net/weixin_43811057/article/details/130798254

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/36184.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JVM 查看配置 jinfo 及使用 jstat,查看堆栈jstack及GC

1. Jinfo 查看正在运行的Java应用程序的扩展参数: 包含 JVM 参数与 java 系统参数 命令&#xff1a; jinfo pid 2 jstat 查看堆内存使用情况及 GC 回收频率等&#xff1a; jstat [-命令选项] [vmid] [间隔时间(毫秒)] [查询次数] 2.1 jstat -gc pid 最常用&#xff0c;可…

C语言必会题目(2)

W...Y的主页 &#x1f60a; 代码仓库分享&#x1f495; 今天继续分享C语言必会的题目&#xff0c;上一篇文章主要是一些选择题&#xff0c;而今天我们主要内容为编程题的推荐与讲解 准备好迎接下面的题了吗&#xff1f;开始发车了&#xff01;&#xff01;&#xff01; 输入…

OSI参考模型及TCP/IP协议栈

一、网络概述 1.1、什么是网络&#xff1f; 1、网络的本质就是实现资源共享 2、将各个系统联系到一起&#xff0c;形成信息传递、接收、共享的信息交互平台 1.2、典型的园区网拓扑 1.3、网络历史发展&#xff0c;ARPA和ARPANET 1、1969年&#xff0c;美国国防部高级研究计…

前后端分离------后端创建笔记(03)前后端对接(下)

本文章转载于【SpringBootVue】全网最简单但实用的前后端分离项目实战笔记 - 前端_大菜007的博客-CSDN博客 仅用于学习和讨论&#xff0c;如有侵权请联系 源码&#xff1a;https://gitee.com/green_vegetables/x-admin-project.git 素材&#xff1a;https://pan.baidu.com/s/…

创新零售,京东重新答题?

继新一轮组织架构调整后&#xff0c;京东从低价到下沉动作不断。 新成立的创新零售部在京东老将闫小兵的带领下悄然完成了整合。近日&#xff0c;京喜拼拼已改名为京东拼拼&#xff0c;与七鲜、前置仓等业务共同承载起京东线上线下加速融合的梦想。 同时&#xff0c;拼拼的更…

【从零学习python 】19. 循环遍历列表和列表嵌套的应用

文章目录 列表的循环遍历1. 使用while循环2. 使用for循环3. 交换2个变量的值1. 列表嵌套2. 应用 进阶案例 列表的循环遍历 1. 使用while循环 为了更有效率的输出列表的每个数据&#xff0c;可以使用循环来完成 namesList [xiaoWang,xiaoZhang,xiaoHua] length len(namesLi…

零售行业供应链管理核心KPI指标(一) – 能力、速度、效率和成本

有关零售行业供应链管理KPI指标的综合性分享&#xff0c;涉及到供应链能力、速度、效率和成本总共九大指标&#xff0c;是一个大框架&#xff0c;比较核心也比较综合。 衡量消费品零售企业供应链管理效率和水平的核心KPI通常有哪些&#xff1f; 图片来源-派可数据&#xff08;…

监控Kafka的关键指标

Kafka 架构 上面绿色部分 PRODUCER&#xff08;生产者&#xff09;和下面紫色部分 CONSUMER&#xff08;消费者&#xff09;是业务程序&#xff0c;通常由研发人员埋点解决监控问题&#xff0c;如果是 Java 客户端也会暴露 JMX 指标。组件运维监控层面着重关注蓝色部分的 BROKE…

Vue 实现重定向、404和路由钩子(六)

一、重定向 1.1 修改 Main.vue <template><div><el-container><el-aside width"200px"><el-menu :default-openeds"[1]"><el-submenu index"1"><template slot"title"><i class"…

MongoDB常用命令

什么是MongoDB ? MongoDB 是由C语言编写的&#xff0c;是一个基于分布式文件存储的开源数据库系统。 在高负载的情况下&#xff0c;添加更多的节点&#xff0c;可以保证服务器性能。 MongoDB 旨在为WEB应用提供可扩展的高性能数据存储解决方案。 MongoDB 将数据存储为一个…

【网络基础实战之路】基于BGP协议中的联邦号连接三个AS区域的实战详解

系列文章传送门&#xff1a; 【网络基础实战之路】设计网络划分的实战详解 【网络基础实战之路】一文弄懂TCP的三次握手与四次断开 【网络基础实战之路】基于MGRE多点协议的实战详解 【网络基础实战之路】基于OSPF协议建立两个MGRE网络的实验详解 【网络基础实战之路】基于…

Dalsa线阵相机说明(Linea Color GigESeries 2k and 4K)

文章目录 一. Dalsa相机软件整体架构二. 相机编号说明以及软件要求三. 相机硬件参数三. 相机基本参数四. 软件参数设置列表1. Sensor Control Category2. I/O Control Category3. Counter and Timer Control Category4. Advanced Processing Control Category(1) 平场校正介绍(…

U盘提示格式化怎么修复?学会这几个方法!

“不知道大家有没有遇到过将u盘插入电脑后提示格式化的情况呀&#xff1f;第一次遇到这种情况真的好无助&#xff0c;这是可以修复的吗&#xff1f;请大家帮帮我&#xff01;” U盘作为一个便捷的存储工具&#xff0c;帮助我们存储了很多重要的数据和文件。但在使用的过程中&am…

PHP8定义字符串的方法-PHP8知识详解

字符串&#xff0c;顾名思义&#xff0c;就是将一堆字符串联在一起。字符串简单的定义方法是使用英文单引号&#xff08; &#xff09;或英文双引号&#xff08;" "&#xff09;包含字符。另外&#xff0c;还可以使用定界符定义字符串。本文还介绍了字符串的连接符。…

TCP的三次握手和四次挥手

文章目录 三次握手四次挥手TIME_WAITCLOSE_WAIT 使用wireshark观察 三次握手 握手的最终目的是主机之间建立连接 首先要有两个预备知识点 三次握手建立连接不一定会成功&#xff0c;其中最担心的就是最后一次握手失败&#xff0c;不过会有配套的解决方案建立好连接后是需要被…

【重温老古董——Strust2框架】基于Idea使用maven创建Strust2项目

1、新建项目 红色圈出的部分是【强制】,其他部分看个人喜好。 2、修改 pom 文件,管理依赖 <dependency><groupId>org.apache.struts</groupId><artifactId>struts2-core</artifactId><version>2.5.22</version></dependency&g…

数据结构:力扣OJ题(每日一练)

目录 题一&#xff1a;环形链表 思路一&#xff1a; 题二&#xff1a;复制带随机指针的链表 思路一&#xff1a; 本人实力有限可能对一些地方解释的不够清晰&#xff0c;可以自己尝试读代码&#xff0c;望海涵&#xff01; 题一&#xff1a;环形链表 给定一个链表的头节点…

IDEA如何调试Stream API

Stream API现在在实际开发中应用非常广泛&#xff0c;经常会遇到需要调试Stream API的场景&#xff0c;这篇文章主要讲解如何使用IDEA调试Stream Testpublic void test(){Stream.of(10, 20, 30, 40, 50).mapToInt(e->e*10).filter(e->e>200).forEach(System.out::pri…

使用css实现时间线布局(TimeLine)

前言 在使用uni-app开发微信小程序过程中&#xff0c;遇到了时间轴布局&#xff0c;由于每项的内容高度不一致&#xff0c;使用uniapp自带的扩展组件uni-steps&#xff0c;样式布局无法对齐竖线&#xff0c;于是自己造轮子&#xff0c;完成特殊的布局。显示效果如下&#xff1…

WebDAV之π-Disk·派盘+Commander One

Commander one是一款为Mac用户设计的双窗格文件管理器,Commander One专业版在原先的版本功能拥有较大的提升。Commander One PRO可以帮助大家将文件从一个地方复制到另一个地方,支持多标签浏览、搜索、自定义热键设置、显示隐藏文件等功能。 π-Disk派盘 – 知识管理专家 派…