基于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.pswp.cn/news/36184.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/36184.shtml
英文地址,請注明出處:http://en.pswp.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/…

數據結構--棧和隊列3.1(棧-順序結構)

目錄 棧&#xff08;Stack&#xff09;棧頂&#xff08;top&#xff09;棧底&#xff08;bottom&#xff09;空棧&#xff08;不含任何元素&#xff09; 創建棧 入棧操作 出棧操作 銷毀一個棧 計算棧的當前容量 實例分析 棧的插入操作叫做進棧&#xff08;Push&#xf…

基于Mybatis Plus的SQL輸出攔截器。完美的輸出打印 SQL 及執行時長、statement

我們需要想辦法打印出完成的SQL&#xff0c;Mybatis為我們提供了 org.apache.ibatis.plugin.Interceptor接口&#xff0c;我們來實現該接口做一些打印SQL的工作 package org.springjmis.core.mp.plugins;import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; impor…

創新零售,京東重新答題?

繼新一輪組織架構調整后&#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;…

C++ unique_ptr概述 常用操作

文章目錄 unique_ptr概述unique_ptr常用操作 unique_ptr概述 uniue_ptr是一個獨占式的指針,同一個時刻, 就只能有一個unique_ptr指向這個對象(內存),unique_ptr的使用格式 unique_ptr<Class_Tyep> P_Name; unique_ptr的常規初始化: unique_ptr<int> p; 創建一個空…

監控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) 平場校正介紹(…

學習Vue:插值表達式和指令

在 Vue.js 中&#xff0c;Vue 實例與數據綁定是構建動態交互界面的關鍵。在這篇文章中&#xff0c;我們將重點介紹 Vue 實例中兩種實現數據綁定的方式&#xff1a;插值表達式和指令。這些機制允許您將數據無縫地渲染到界面上&#xff0c;實現實時的數據更新和展示。 插值表達式…

U盤提示格式化怎么修復?學會這幾個方法!

“不知道大家有沒有遇到過將u盤插入電腦后提示格式化的情況呀&#xff1f;第一次遇到這種情況真的好無助&#xff0c;這是可以修復的嗎&#xff1f;請大家幫幫我&#xff01;” U盤作為一個便捷的存儲工具&#xff0c;幫助我們存儲了很多重要的數據和文件。但在使用的過程中&am…

Dockerfile 使用技巧篇

默認的 docker 鏡像使用 Linux 來當作基礎鏡像 01. 使用 alpine 鏡像&#xff0c;而不是默認的 linux 鏡像 PS: alpine 譯為高山植物&#xff0c;就是很少的資源就能存活的意思。alpine 裁剪了很多不必要的 linux 功能&#xff0c;使得鏡像體積大幅減小了。 比如 FROM node:1…

PHP8定義字符串的方法-PHP8知識詳解

字符串&#xff0c;顧名思義&#xff0c;就是將一堆字符串聯在一起。字符串簡單的定義方法是使用英文單引號&#xff08; &#xff09;或英文雙引號&#xff08;" "&#xff09;包含字符。另外&#xff0c;還可以使用定界符定義字符串。本文還介紹了字符串的連接符。…

TCP的三次握手和四次揮手

文章目錄 三次握手四次揮手TIME_WAITCLOSE_WAIT 使用wireshark觀察 三次握手 握手的最終目的是主機之間建立連接 首先要有兩個預備知識點 三次握手建立連接不一定會成功&#xff0c;其中最擔心的就是最后一次握手失敗&#xff0c;不過會有配套的解決方案建立好連接后是需要被…