当前位置: 首页 > news >正文

【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);}
}

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

在这里插入图片描述

相关文章:

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

文章目录 &#x1f354;生成全局唯一ID&#x1f339;为什么要生成全局唯一id&#x1f33a;生成全局id的方法✨代码实现 &#x1f354;生成全局唯一ID 是一种在分布式系统下用来生成全局唯一id的工具 在项目中生成全局唯一ID有很多好处&#xff0c;其中包括&#xff1a; 数据…...

轻度听力损失的儿童需要早期干预吗?

一些宝宝在做听力筛查时总是不通过&#xff0c;进一步听力诊断发现宝宝有轻度的听力损失&#xff0c;刚知道这个消息时&#xff0c;家长可担心了&#xff0c;总想着宝宝是不是听不到啊&#xff1f;但是一段时间后&#xff0c;有些家长又会忽略宝宝的听力问题&#xff0c;因为部…...

【Spring Security】认证密码加密Token令牌CSRF的使用详解

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是Java方文山&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的专栏《Spring Security》。&#x1f3af;&#x1f3af; …...

python一点通: 一文讲清Post 和 Put操作区别!

当我们使用网络服务时&#xff0c;如果我们不能小心地区分 POST 和 PUT&#xff0c;有时可能会触发错误。 在 Web 开发世界中&#xff0c;特别是在处理 RESTful API 时&#xff0c;HTTP 方法 POST 和 PUT 经常被使用&#xff0c;但常常被误解。这两者都用于向服务器发送数据&a…...

通过 Higress Wasm 插件 3 倍性能实现 Spring-cloud-gateway 功能

作者&#xff1a;韦鑫&#xff0c;Higress Committer&#xff0c;来自南京航空航天大学分布式系统实验室 导读&#xff1a;本文将和大家一同回顾 Spring Cloud Gateway 是如何满足 HTTP 请求/响应转换需求场景的&#xff0c;并为大家介绍在这种场景下使用 Higress 云原生网关的…...

0.618算法和基于Armijo准则的线搜索回退法

0.618代码如下&#xff1a; import math # 定义函数h(t) t^3 - 2t 1 def h(t): return t**3 - 2*t 1 # 0.618算法 def golden_section_search(a, b, epsilon): ratio 0.618 while (b - a) > epsilon: x1 b - ratio * (b - a) x2 a ratio * (b - a) h_…...

DPDK单步跟踪(3)-项目配置和单步跟踪

项目配置 下面都是示例的情况&#xff0c;请大家根据自己的工程来修改 ## 首先是配置CMake build setting Debug setting 这里最重要的是&#xff1a; –proc-type secondary 表示这是以secondary模式启动的dpdk客户端。 ## path mapping 然后根据自己的需要&#xff0c;配置…...

.NET core 自定义过滤器 Filter 实现webapi RestFul 统一接口数据返回格式

之前写过使用自定义返回类的方式来统一接口数据返回格式&#xff0c;.Net Core webapi RestFul 统一接口数据返回格式-CSDN博客 但是这存在一个问题&#xff0c;不是所有接口会按照定义的数据格式返回&#xff0c;除非每个接口都返回我们自定义的类&#xff0c;这种实现起来不…...

vue3 使用addRoute动态添加路由,页面刷新就白屏解决办法

问题&#xff0c;通过接口动态添加路由&#xff0c;第一次从登录页跳转还是正常的&#xff0c;说明路由添加成功了&#xff0c;但是刷新后就白屏了&#xff0c;且控制台报错路由匹配不到&#xff0c;在项目的main.js&#xff0c;router和路由拦截器中添加了一大堆打印后发现&am…...

探索鸿蒙:了解华为鸿蒙操作系统的基础课程

目录 学习目标&#xff1a; 学习内容&#xff1a; 学习时间&#xff1a; 学习产出&#xff1a; 介绍鸿蒙操作系统的起源和发展历程。 理解鸿蒙操作系统的核心概念和体系结构。 学习如何搭建和配置鸿蒙开发环境。 掌握基础的鸿蒙应用开发技术&#xff0c;包括应用的创建、…...

【Linux】进程周边007之进程控制

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 目录 前言 1.进程创建 2.进程终止 2.…...

【C++】vector容器的模拟实现

目录 一&#xff0c;框架设计 二&#xff0c;构造函数 三&#xff0c;析构函数 四&#xff0c;赋值运算符 五&#xff0c;容器接口的实现 1&#xff0c;迭代器实现 2&#xff0c;“ [] ”运算符的实现 3&#xff0c;swap交换和resize重设大小 4&#xff0c;insert插入…...

华为Harmony——ArkTs语言

文章目录 一、简单示例二、声明式UI描述创建组件无参有参数 配置属性配置事件配置子组件 三、自定义组件基本用法基本结构成员函数/变量 一、简单示例 我们以一个具体的示例来说明ArkTS的基本组成。如下图所示&#xff0c;当开发者点击按钮时&#xff0c;文本内容从“Hello Wo…...

uniapp使用colorUI

colorUI 微动画 | ColorUI 使用文档 1&#xff1a;把colorui里三个文件复制到自己项目中去 App.vue </script> <style> import url(colorui/icon.css); import url(colorui/main.css); import url("colorui/animation.css");-webkit-keyframes show {…...

浅谈测试自动化selenium之POM模式

基于本人也是一个初学者&#xff0c;在运用POM模式的时候记录一下自己的学习笔记。 如果你是大神&#xff0c;那么可以略过&#xff0c;如果你是初学者&#xff0c;希望对你有帮助。 本文阐述了以下几个问题&#xff1a; 什么叫POM模式 为什么要用POM模式 POM模式的思想 POM模…...

什么是事件传播、事件冒泡、事件捕获?

一、事件传播 1、概述 &#xff08;1&#xff09;当事件发生在DOM元素上时&#xff0c;该事件并不完全发生在那个元素 &#xff08;2&#xff09;在冒泡阶段中&#xff0c;事件冒泡或向上传播至父级、祖父级、祖父的父级&#xff0c;直到 window 为止 &#xff08;3&#x…...

【uniapp】uniapp中本地存储sqlite数据库保姆级使用教程(附完整代码和注释)

数据库请求接口封装 uniapp中提供了plus.sqlite接口&#xff0c;在这里我们对常用的数据库请求操作进行了二次封装 这里的dbName、dbPath、recordsTable 可以根据你的需求自己命名 module.exports {/** * type {String} 数据库名称*/dbName: salary,/*** 数据库地址* type {…...

微软推出了GPT-RAG:这是一个机器学习库,为在Azure OpenAI上使用RAG模式生产部署大型语言模型(LLMs)提供了企业级参考架构

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…...

Centos系统升级gcc版本

自己环境的gcc版本太低&#xff0c;影响使用SAN全家桶进行内存泄露检查 当前环境gcc版本查看 gcc --version 进行升级&#xff1a; 1、安装EPEL存储库 yum install epel-release -y 2、确保系统已经更新到最新版本 yum update -y 3、安装GCC编译器及其相关工具包 yum g…...

Http---HTTP响应报文

1. HTTP响应报文分析 HTTP 响应报文效果图: 响应报文说明: --- 响应行/状态行 --- HTTP/1.1 200 OK # HTTP协议版本 状态码 状态描述 --- 响应头 --- Server: Tengine # 服务器名称 Content-Type: text/html; charsetUTF-8 # 内容类型 Transfer-Encoding: chunked # 发送给客…...

云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?

大家好&#xff0c;欢迎来到《云原生核心技术》系列的第七篇&#xff01; 在上一篇&#xff0c;我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在&#xff0c;我们就像一个拥有了一块崭新数字土地的农场主&#xff0c;是时…...

Vue记事本应用实现教程

文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展&#xff1a;显示创建时间8. 功能扩展&#xff1a;记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...

FFmpeg 低延迟同屏方案

引言 在实时互动需求激增的当下&#xff0c;无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作&#xff0c;还是游戏直播的画面实时传输&#xff0c;低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架&#xff0c;凭借其灵活的编解码、数据…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序

一、开发环境准备 ​​工具安装​​&#xff1a; 下载安装DevEco Studio 4.0&#xff08;支持HarmonyOS 5&#xff09;配置HarmonyOS SDK 5.0确保Node.js版本≥14 ​​项目初始化​​&#xff1a; ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...

PL0语法,分析器实现!

简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...

自然语言处理——循环神经网络

自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元&#xff08;GRU&#xff09;长短期记忆神经网络&#xff08;LSTM&#xff09…...

聊一聊接口测试的意义有哪些?

目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开&#xff0c;首…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)

目录 一、&#x1f44b;&#x1f3fb;前言 二、&#x1f608;sinx波动的基本原理 三、&#x1f608;波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、&#x1f30a;波动优化…...

MySQL账号权限管理指南:安全创建账户与精细授权技巧

在MySQL数据库管理中&#xff0c;合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号&#xff1f; 最小权限原则&#xf…...

短视频矩阵系统文案创作功能开发实践,定制化开发

在短视频行业迅猛发展的当下&#xff0c;企业和个人创作者为了扩大影响力、提升传播效果&#xff0c;纷纷采用短视频矩阵运营策略&#xff0c;同时管理多个平台、多个账号的内容发布。然而&#xff0c;频繁的文案创作需求让运营者疲于应对&#xff0c;如何高效产出高质量文案成…...