平頂山網(wǎng)站建設(shè)費用競價排名是什么
Redis:實現(xiàn)全局唯一ID
- 一. 概述
- 二. 實現(xiàn)
- (1)獲取初始時間戳
- (2)生成全局ID
- 三. 測試
- 為什么可以實現(xiàn)全局唯一?
- 其他唯一ID策略
- 補充:countDownLatch
一. 概述
全局ID生成器:是一種在【分布式系統(tǒng)下】用來生成全局唯一ID的工具;
全局ID需要滿足的特性:
1.唯一性
2.高可用:集群、哨兵機(jī)制;
3.高性能
4.遞增性:Redis中的String數(shù)據(jù)類型的有自增特性!
5.安全性:將自增數(shù)值進(jìn)行拼接,不容易猜出來;
ID結(jié)構(gòu):
符號位(1位) + 時間戳
(31位) + 序列號
(32位);
時間戳為從起始時間
到現(xiàn)在的時間差;
理論上支持1秒鐘2^32個訂單;
二. 實現(xiàn)
(1)獲取初始時間戳
先設(shè)定一個初始時間如2022年1月1日,獲取初始時間的時間戳;
(2)生成全局ID
- 在utl層中定義一個
RedisIdWorker
類的bean; - 寫一個方法,返回值是long型;不同業(yè)務(wù)要區(qū)別,所以使用前綴區(qū)分業(yè)務(wù);
- 生成
時間戳
:即當(dāng)前時間秒數(shù) - 初始時間秒數(shù); - 生成
序列號
:使用stringRedisTemplate中String類型的自增方法increment()/INCR
,而key(2^32)遲早會用完存不下,所以不能使用同一個key來自增,
序列號的key:所以使用精確到天的時間作為key,這樣一個key就對應(yīng)一天,不同天數(shù)的key不同,這樣key的上限就是一天的下單量即2^32個,key夠用;這樣還方便統(tǒng)計訂單量;
- 拼接前綴 + 符號位 + 時間戳 + 序列號,先使用位運算,將時間戳左移32位(序列號的位數(shù)),最低位都會變成0;
然后把序列號count拼接上去:使用或運算填充,有1則1,否則為0;
三. 測試
- 用工廠方法創(chuàng)建線程池,容量500;
- 創(chuàng)建一個任務(wù),在任務(wù)中生成并 打印ID100次,共給線程池提交300次任務(wù);
由于線程池會異步執(zhí)行,使用countDownLatch
,300個線程,每個線程會countdown
一次,直到計數(shù)為0就會喚醒await()
所在的當(dāng)前線程,就會去main中打印所花的時間了;
結(jié)果:生成共3w個ID;
查看Redis:
為什么可以實現(xiàn)全局唯一?
因為生成ID時用的是Redis的 increment / INCR
功能,每調(diào)用一次都會進(jìn)行自增;
其他唯一ID策略
Redis產(chǎn)生的ID是數(shù)值類型long,占空間小;
UUID:JDK自帶,16進(jìn)制字符串,不是自增的,不滿足要求;
雪花snowflake算法:需要維護(hù)機(jī)器id,對于時鐘依賴比較高;
數(shù)據(jù)庫實現(xiàn),性能不如Redis;
補充:countDownLatch
用來進(jìn)行線程同步協(xié)作,等待所偶有線程完成倒計時;
其中構(gòu)造參數(shù)用來初始化等待計數(shù)值,countDown()
用來計數(shù)-1,await()
用來等待技術(shù)歸零,歸零后就會執(zhí)行當(dāng)前線程;