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("耗時:"+(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緩存保存數據成功");
? ? ? ? ? ? ? ? ? ? entityIdCounter= new RedisAtomicLong("ceid", redisTemplate.getConnectionFactory());
? ? ? ? ? ? ? ? ? ? //incr 默認初始值從0開始,
? ? ? ? ? ? ? ? ? ? //可以設置初始值,
? ? ? ? ? ? ? ? ? ? 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:失敗,返回上個id");
? ? ? ? ? ? ? ? }else{
? ? ? ? ? ? ? ? ? ? System.out.println(increment);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
?
? ? ? ? }
? ? }
?
}redis配置在application.properties中
# REDIS # Redis數據庫索引(默認為0) spring.redis.database=0 ? # Redis服務器地址 (默認為127.0.0.1) spring.redis.host=127.0.0.1 # Redis服務器連接端口 (默認為6379) spring.redis.port=6379 ? # Redis服務器連接密碼(默認為空) spring.redis.password= ? # 連接超時時間(毫秒) spring.redis.timeout=2000ms
springboot redis自增編號控制 踩坑
近段期間,公司 接手一個訂單號生成服務,規(guī)則的話已經由項目經理他們規(guī)定好了,主要是后面的四位數代表的關于當前訂單號已經執(zhí)行第幾個了。而這里面有一個要求就是支持分布式。
為了實現這個東西,剛開始我使用了redis的incr來解決這個問題,因為我們后端開發(fā)用的是Spring boot,所以我網上找了一個代碼如下:
/**
*
* @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) {//初始設置過期時間
entityIdCounter.expire(liveTime, TimeUnit.SECONDS);
}
return increment;
}結果測試的時候,看著后面的數很滿意,心里面有點小小的激動哦~~
但是當我將數據從小到大排序的時候,發(fā)現了一點異樣,即剛開始的幾個是存在問題的。
所以通過測試發(fā)現了,當redis里面還沒有設置計時器的一剎那,分布式服務下,會存在前幾個重復的現象。

發(fā)現這個問題之后,于是我通過redis鎖,當判斷redis下面還沒存在計數key的情況下,鎖住,然后在鎖住的情況下,其他人進來調用的時候,線程睡眠500ms,然后再往下執(zhí)行。順利解決~~~
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
http調用controller方法時openfeign執(zhí)行流程
這篇文章主要為大家介紹了http調用controller方法時openfeign執(zhí)行流程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-07-07
SpringBoot如何配置文件properties和yml
這篇文章主要介紹了SpringBoot如何配置文件properties和yml問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-08-08

