springboot如何使用redis的incr創(chuàng)建分布式自增id
使用redis的incr創(chuàng)建分布式自增id
測試使用springboot加載類測試,使用本地redis, 模擬多線程去生成規(guī)律的自增id
@Component public class Common implements CommandLineRunner { ? ? @Autowired ? ? private RedisTemplate redisTemplate; ? ? ? @Override ? ? public void run(String... args) throws Exception { ? ? ? ? long start = System.currentTimeMillis(); ? ? ? ? Thread thread1 = new Thread(new Test1()); ? ? ? ? Thread thread2 = new Thread(new Test1()); ? ? ? ? Thread thread3 = new Thread(new Test1()); ? ? ? ? thread1.start(); ? ? ? ? thread2.start(); ? ? ? ? thread3.start(); ? ? ? ? long end = System.currentTimeMillis(); ? ? ? ? System.out.println("耗時(shí):"+(end-start)); ? ? } ? ? ? class Test1 implements Runnable{ ? ? ? ? ? @Override ? ? ? ? public void run() { ? ? ? ? ? ? getId(); ? ? ? ? ? } ? ? ? } ? ? ? public void getId(){ ? ? ? ? synchronized (this) { ? ? ? ? ? ? RedisAtomicLong entityIdCounter = null; ? ? ? ? ? ? ? for(int i=0;i<10;i++){ ? ? ? ? ? ? ? ? if(!redisTemplate.hasKey("ceid")){ ? ? ? ? ? ? ? ? ? ? redisTemplate.opsForValue().increment("ceid", 1); ? ? ? ? ? ? ? ? ? ? System.out.println("test1使用redis緩存保存數(shù)據(jù)成功"); ? ? ? ? ? ? ? ? ? ? entityIdCounter= new RedisAtomicLong("ceid", redisTemplate.getConnectionFactory()); ? ? ? ? ? ? ? ? ? ? //incr 默認(rèn)初始值從0開始, ? ? ? ? ? ? ? ? ? ? //可以設(shè)置初始值, ? ? ? ? ? ? ? ? ? ? entityIdCounter.set(123); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? entityIdCounter=new RedisAtomicLong("ceid", redisTemplate.getConnectionFactory()); ? ? ? ? ? ? ? ? long increment=0; ? ? ? ? ? ? ? ? ? increment = entityIdCounter.incrementAndGet(); ? ? ? ? ? ? ? ? if (i == 5) { ? ? ? ? ? ? ? ? ? ? increment = entityIdCounter.decrementAndGet(); ? ? ? ? ? ? ? ? ? ? System.out.println("test1:失敗,返回上個(gè)id"); ? ? ? ? ? ? ? ? }else{ ? ? ? ? ? ? ? ? ? ? System.out.println(increment); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? ? } ? ? } ? }
redis配置在application.properties中
# REDIS # Redis數(shù)據(jù)庫索引(默認(rèn)為0) spring.redis.database=0 ? # Redis服務(wù)器地址 (默認(rèn)為127.0.0.1) spring.redis.host=127.0.0.1 # Redis服務(wù)器連接端口 (默認(rèn)為6379) spring.redis.port=6379 ? # Redis服務(wù)器連接密碼(默認(rèn)為空) spring.redis.password= ? # 連接超時(shí)時(shí)間(毫秒) spring.redis.timeout=2000ms
springboot redis自增編號控制 踩坑
近段期間,公司 接手一個(gè)訂單號生成服務(wù),規(guī)則的話已經(jīng)由項(xiàng)目經(jīng)理他們規(guī)定好了,主要是后面的四位數(shù)代表的關(guān)于當(dāng)前訂單號已經(jīng)執(zhí)行第幾個(gè)了。而這里面有一個(gè)要求就是支持分布式。
為了實(shí)現(xiàn)這個(gè)東西,剛開始我使用了redis的incr來解決這個(gè)問題,因?yàn)槲覀兒蠖碎_發(fā)用的是Spring boot,所以我網(wǎng)上找了一個(gè)代碼如下:
/** * * @param key * @param liveTime * @return */ public Long incr(String key, long liveTime) { RedisAtomicLong entityIdCounter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory()); Long increment = entityIdCounter.getAndIncrement(); if ((null == increment || increment.longValue() == 0) && liveTime > 0) {//初始設(shè)置過期時(shí)間 entityIdCounter.expire(liveTime, TimeUnit.SECONDS); } return increment; }
結(jié)果測試的時(shí)候,看著后面的數(shù)很滿意,心里面有點(diǎn)小小的激動(dòng)哦~~
但是當(dāng)我將數(shù)據(jù)從小到大排序的時(shí)候,發(fā)現(xiàn)了一點(diǎn)異樣,即剛開始的幾個(gè)是存在問題的。
所以通過測試發(fā)現(xiàn)了,當(dāng)redis里面還沒有設(shè)置計(jì)時(shí)器的一剎那,分布式服務(wù)下,會存在前幾個(gè)重復(fù)的現(xiàn)象。
發(fā)現(xiàn)這個(gè)問題之后,于是我通過redis鎖,當(dāng)判斷redis下面還沒存在計(jì)數(shù)key的情況下,鎖住,然后在鎖住的情況下,其他人進(jìn)來調(diào)用的時(shí)候,線程睡眠500ms,然后再往下執(zhí)行。順利解決~~~
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- SpringBoot中dubbo+zookeeper實(shí)現(xiàn)分布式開發(fā)的應(yīng)用詳解
- 2020最新IDEA SpringBoot整合Dubbo的實(shí)現(xiàn)(zookeeper版)
- SpringBoot系列教程之dubbo和Zookeeper集成方法
- 淺談Java(SpringBoot)基于zookeeper的分布式鎖實(shí)現(xiàn)
- SpringBoot整合XxlJob分布式任務(wù)調(diào)度平臺
- SpringBoot?2.5.5整合輕量級的分布式日志標(biāo)記追蹤神器TLog的詳細(xì)過程
- SpringBoot集成redis與session實(shí)現(xiàn)分布式單點(diǎn)登錄
- springboot 使用zookeeper實(shí)現(xiàn)分布式隊(duì)列的基本步驟
相關(guān)文章
Java中實(shí)現(xiàn)簡單的Excel導(dǎo)出
今天小編就為大家分享一篇關(guān)于Java中實(shí)現(xiàn)簡單的Excel導(dǎo)出,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-01-01java查找字符串中的包含子字符串的個(gè)數(shù)實(shí)現(xiàn)代碼
下面小編就為大家?guī)硪黄猨ava查找字符串中的包含子字符串的個(gè)數(shù)實(shí)現(xiàn)代碼。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-06-06RocketMQ實(shí)現(xiàn)隨緣分BUG小功能示例詳解
這篇文章主要為大家介紹了RocketMQ實(shí)現(xiàn)隨緣分BUG小功能示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08mybatis-plus查詢無數(shù)據(jù)問題及解決
這篇文章主要介紹了mybatis-plus查詢無數(shù)據(jù)問題及解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12http調(diào)用controller方法時(shí)openfeign執(zhí)行流程
這篇文章主要為大家介紹了http調(diào)用controller方法時(shí)openfeign執(zhí)行流程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07淺談java運(yùn)用注解實(shí)現(xiàn)對類中的方法檢測的工具
這篇文章主要介紹了淺談java運(yùn)用注解實(shí)現(xiàn)對類中的方法檢測的工具,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08SpringBoot如何配置文件properties和yml
這篇文章主要介紹了SpringBoot如何配置文件properties和yml問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08