【SpringBoot篇】基于Redis实现生成全局唯一ID的方法

文章目录

  • 🍔生成全局唯一ID
  • 🌹为什么要生成全局唯一id
  • 🌺生成全局id的方法
  • ✨代码实现

在这里插入图片描述

🍔生成全局唯一ID

是一种在分布式系统下用来生成全局唯一id的工具
请添加图片描述

在项目中生成全局唯一ID有很多好处,其中包括:

  • 数据库主键:在数据库中,唯一ID可以作为主键,确保每条记录的唯一性,便于快速检索和更新数据。
  • 分布式系统:在分布式系统中,生成全局唯一ID可以避免不同节点生成相同的ID,确保整个系统的数据一致性。
  • 日志追踪:在日志系统中,给每条日志分配唯一ID可以方便进行日志的追踪和分析。
  • 安全性:某些场景下,需要对数据进行加密或者数据权限控制,唯一ID可以作为安全机制的一部分。
  • 缓存键值:在缓存系统中,使用唯一ID作为键值可以避免不同数据之间的冲突。
  • 数据分片:在分布式存储系统中,唯一ID可以作为数据分片的标识,便于数据的存储和查询。

总之,生成全局唯一ID有助于提高系统的可用性、数据的完整性和安全性,同时也方便数据的管理和分析。因此,在许多项目中都会需要生成全局唯一ID来满足系统的需求。

🌹为什么要生成全局唯一id

生成全局唯一ID的主要目的是确保系统中的实体(如对象、记录、消息等)具有唯一性标识。以下是一些常见的原因:

  • 数据唯一性:全局唯一ID可以确保在系统中每个实体都有一个独一无二的标识符,避免数据冲突和重复。
  • 数据库索引:全局唯一ID通常用作数据库表的主键或索引,以提高数据查询和检索的效率。
  • 分布式系统:在分布式系统中,各个节点可能同时生成ID,为了避免ID的冲突,需要使用全局唯一ID算法确保整个系统中的ID唯一性。
  • 数据跟踪与关联:通过给实体分配唯一ID,可以轻松追踪和关联数据,例如日志记录、事务管理、审计等。
  • 安全性和权限控制:全局唯一ID可以用于确保数据的安全性和权限控制,限制对特定实体的访问和操作。
  • 缓存与缓存失效:在缓存系统中,使用全局唯一ID作为缓存键,可以确保不同实体之间的键不会冲突,并且在缓存失效时能够正确地重新加载数据。

总结来说,生成全局唯一ID有助于确保数据的唯一性、提高系统的可用性和性能,并支持数据跟踪、安全性和权限控制等功能。这在许多系统和应用中都是一个重要的需求。

🌺生成全局id的方法

请添加图片描述

✨代码实现

ID生成器的算法如下
在这里插入图片描述

我们要先生成时间戳,在生成序列号,然后进行拼接

package com.hmdp.utils;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 {/*** 开始时间戳*/private static final long BEGIN_TIMESTAMP = 1640995200L;/*** 序列号的位数*/private static final int COUNT_BITS = 32;private StringRedisTemplate stringRedisTemplate;public RedisIdWorker(StringRedisTemplate stringRedisTemplate) {this.stringRedisTemplate = stringRedisTemplate;}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.自增长long count = stringRedisTemplate.opsForValue().increment("icr:" + keyPrefix + ":" + date);// 3.拼接并返回return timestamp << COUNT_BITS | count;}
}

这段代码的 timestamp << COUNT_BITS | count;是怎么算出序列号的
在这里插入图片描述

在这段代码中,timestamp << COUNT_BITS | count 是通过位运算来生成最终的ID值。

首先,timestamp 是时间戳,代表了从开始时间戳到当前时间的秒数差。COUNT_BITS 是序列号的位数,这里是32位。

位运算符 << 是左移操作符,将 timestamp 的二进制表示向左移动 COUNT_BITS 位,就是将时间戳占据高位。这样做是为了给序列号腾出足够的空间

然后,使用位运算符 | 进行按位或操作,将左移后的时间戳与序列号 count 进行按位或操作,合并它们的二进制表示。

最终得到的结果就是一个64位的ID,其中高位是时间戳部分,低位是序列号部分。

编写代码进行测试
在这里插入图片描述

package com.hmdp;import com.hmdp.entity.Shop;
import com.hmdp.service.impl.ShopServiceImpl;
import com.hmdp.utils.CacheClient;
import com.hmdp.utils.RedisIdWorker;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.StringRedisTemplate;import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;import static com.hmdp.utils.RedisConstants.CACHE_SHOP_KEY;
import static com.hmdp.utils.RedisConstants.SHOP_GEO_KEY;@SpringBootTest
class HmDianPingApplicationTests {@Resourceprivate CacheClient cacheClient;@Resourceprivate ShopServiceImpl shopService;@Resourceprivate RedisIdWorker redisIdWorker;private ExecutorService es = Executors.newFixedThreadPool(500);@Testvoid testIdWorker() throws InterruptedException {CountDownLatch latch = new CountDownLatch(300);Runnable task = () -> {for (int i = 0; i < 100; i++) {long id = redisIdWorker.nextId("order");System.out.println("id = " + id);}latch.countDown();};long begin = System.currentTimeMillis();for (int i = 0; i < 300; i++) {es.submit(task);}latch.await(); //等待上面的结束long end = System.currentTimeMillis();System.out.println("time = " + (end - begin));}@Testvoid testSaveShop() throws InterruptedException {Shop shop = shopService.getById(1L);cacheClient.setWithLogicalExpire(CACHE_SHOP_KEY + 1L, shop, 10L, TimeUnit.SECONDS);}
}

在技术的道路上,我们不断探索、不断前行,不断面对挑战、不断突破自我。科技的发展改变着世界,而我们作为技术人员,也在这个过程中书写着自己的篇章。让我们携手并进,共同努力,开创美好的未来!愿我们在科技的征途上不断奋进,创造出更加美好、更加智能的明天!

在这里插入图片描述

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

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

相关文章

sql-labs服务器结构

双层服务器结构 一个是tomcat的jsp服务器&#xff0c;一个是apache的php服务器&#xff0c;提供服务的是php服务器&#xff0c;只是tomcat向php服务器请求数据&#xff0c;php服务器返回数据给tomcat。 此处的29-32关都是这个结构&#xff0c;不是用docker拉取的镜像要搭建一下…

【Python】异常、模块与包

一、异常的概念 二、异常的捕获方法 三、异常的传递 四、Python模块 五、Python包 六、安装第三方Python包 一、异常的概念 什么是异常&#xff1a; 异常就是程序运行的过程中出现了错误bug是什么意思&#xff1a; bug就是指异常的意思&#xff0c;因为历史因为小虫子导致计算…

ansible-playbook的Temlates模块 tags模块 Roles模块

Temlates模块 jinja模板架构&#xff0c;通过模板可以实现向模板文件传参(python转义)把占位符参数传到配置文件中去,生产一个目标文本文件&#xff0c;传递变量到需要的配置文件当中 &#xff08;web开发&#xff09; nginx.conf.j2 早文件当中配置的是占位符&#xff08;声明…

Error in `arrange()`: ! Can‘t transform a data frame with `NA` or `““` names.

问题&#xff1a;给Taxonomy排序&#xff0c;并筛选OTU表中存在的 根据提示运行&#xff1a;rlang::last_error()&#xff0c;显示&#xff1a; Backtrace:▆1. ├─dplyr::arrange(taxonomy, phylum, class, order, family, full)2. ├─dplyr:::arrange.data.frame(taxonom…

【SpringBoot篇】解决缓存击穿问题① — 基于互斥锁方式

文章目录 &#x1f339;什么是缓存击穿&#x1f33a;基于互斥锁解决问题&#x1f6f8;思路 &#x1f3f3;️‍&#x1f308;代码实现 &#x1f339;什么是缓存击穿 缓存击穿是指在使用缓存系统时&#xff0c;对一个热点数据的高并发请求导致缓存失效&#xff0c;多个请求同时访…

云渲染怎么批量效果图、影视动画?云渲染在效果图、影视的作用

在设计和建筑领域&#xff0c;设计师往往需要制作出精细逼真的效果图以向客户展示他们的设计思路。然而&#xff0c;在这些行业中&#xff0c;大量生成效果图需求非常费时费力。幸运的是&#xff0c;日期到了云渲染的这个时代&#xff0c;设计师们可以通过云渲染服务以一种更加…

小程序面试题 | 12.精选小程序面试题

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

帕累托森林CEO李朝政博士受邀「OSS-Compass」开源年会畅谈:开源框架下的奇异竞争规则

导语 “怎么在别人知道你的代码和战略时&#xff0c;你仍然拥有壁垒&#xff1f;”这是开源框架下&#xff0c;商业必须思考的问题。 软件驱动世界运转。但当基础层代码失去了有深度活力的“动态延伸”潜力&#xff0c;便会遭致市场“零定价”的宿命。动态延伸的效率&#xf…

用html,css和js写购物车移动端加减全反选及计算总价

目录 html代码 css代码 js代码 完整代码 效果图 html代码 <script src"./flexible.js"></script><!-- <script src"https://cdn.jsdelivr.net/npm/vue2/dist/vue.js"></script> --><div class"header">…

基于iOS平台的车牌识别表情识别项目

基于iOS平台的车牌识别&&表情识别项目 简介 ​ 该项目客户端搭载于iOS平台&#xff0c;服务端搭载于阿里云服务器&#xff0c;主要功能是通过拍照或选取相册图片来进行车牌的识别以及人脸表情识别。本文便是对项目整体流程设计思路和具体实现做一个详细介绍。 整体实…

Android App程序应用未校验签名证书——————《风险等级高》

目录 应用签名未校验风险1、检测目的2、风险等级3、检测依据4、风险描述5、检测步骤6、结果描述7、解决方案7.1、Android 检验 APK 是否签名的代码7.2、检验APK签名 8、结尾 应用签名未校验风险 1、检测目的 检测App程序启动时是否校验签名证书。 防止App的盗版率。未进行签…

Set A Light 3D Studio for Mac - 构建逼真的照明场景!

Set A Light 3D Studio 是一款专业的照明设计和模拟软件&#xff0c;旨在帮助摄影师、电影制片人和视觉艺术家创建逼真的照明场景。无论你是在拍摄电影、广告、时尚杂志还是其他视觉艺术项目&#xff0c;这个软件都能帮助你实现你的创意想法。 Set A Light 3D Studio Mac版 ✨…

【C++入门到精通】 原子性操作库(atomic) C++11 [ C++入门 ]

阅读导航 引言一、原子性操作库简介二、原子变量1. 原子类型2. 原子类型函数3. 使用示例 三、总结温馨提示 引言 当谈及并发编程时&#xff0c;确保数据的安全性和一致性是至关重要的。在C11中引入的原子性操作库&#xff08;atomic&#xff09;为我们提供了一种有效且可靠的方…

2004年AMC8数学竞赛中英文真题典型考题、考点分析和答案解析

今天距离2024年的AMC8美国数学竞赛举办已不足一个月了&#xff0c;赶紧利用周末的时间刷刷真题&#xff0c;查漏补缺吧&#xff01;如果您有任何关于AMC8比赛的任何问题都可以问我&#xff0c;关于题目的解析也可以交流。 今天六分成长继续和您一起&#xff0c;从历年的真题中来…

Ubuntu 常用命令之 man 命令用法介绍

&#x1f4d1;Linux/Ubuntu 常用命令归类整理 man命令在Ubuntu系统中是一个非常重要的命令&#xff0c;它用于查看系统的手册页。手册页是Linux和Unix系统中的一种在线文档&#xff0c;用于描述系统中的命令、函数、配置文件等的详细信息。 man命令的基本格式是 man [选项] …

FPC柔性线路板使用UV胶水的优势有哪些?

UV胶水在FPC柔性线路板的装配中具有明显的优势&#xff1a; 快速固化 UV胶水在紫外线照射后10秒左右迅速固化&#xff0c;因此它能够在短时间内完成连接。这非常有助于实际工业作业中提高生产效率&#xff0c;特别是在需要大批量生产的情况下。 精确控制固化时间 UV胶水的固…

pip 常用指令 pip cache 命令用法介绍

&#x1f4d1;pip 常用命令归类整理 pip cache 是一个用于管理pip缓存的命令。pip是Python的包管理器&#xff0c;用于安装和管理Python包。当你使用pip安装一个包时&#xff0c;pip会首先在其缓存中查找该包。如果在缓存中找到&#xff0c;pip将从缓存中安装该包&#xff0c;…

【ARM 安全系列介绍 3.4 -- 安全证书介绍】

文章目录 安全证书安全证书的主要组成部分安全证书的应用场景证书使用举例 证书格式PEM (Privacy Enhanced Mail)DER (Distinguished Encoding Rules)PKCS#7/P7B (Public Key Cryptography Standards #7)PKCS#12/PFX (Public Key Cryptography Standards #12)P7B 和 PFX/P12 的…

Vue 在同一个项目中,判断pc端和移动端,显示不同风格的页面(附pc端移动端显示效果图)

实现思路 1、修改index.html页面的meta 2、增加pc端移动端的判断 3、设置路由&#xff0c;根据不同的端&#xff0c;调用各自的路由&#xff0c;显示不同的页面 index.html 修改如下 <meta name"viewport" content"widthdevice-width,initial-scale1.0,minim…

51单片机模数转换ADC原理与代码一

51单片机模数转换ADC原理与代码一 1.概述 这篇文章是模数转换的入门文章&#xff0c;这篇文章主要介绍模数的概念、原理、核心指标、专业术语&#xff0c;以及一个模数转换的实例代码实现检测电位器的数值变化。 2.ADC介绍 2.1.ADC概念 ADC(Analog-to-Digital Converter)是…