最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于Redis實現(xiàn)的分布式唯一編號生成工具類

 更新時間:2025年11月20日 09:39:28   作者:她說..  
這篇文章主要介紹了基于Redis實現(xiàn)的分布式唯一編號生成工具類,核心功能是生成格式為 業(yè)務(wù)編碼+日期+3位自增序號(如 JJ20250826001)的全局唯一編號,適用于分布式系統(tǒng)中需要有序、不重復(fù)編號的場景(如訂單號、單據(jù)號等),以下是詳細(xì)解析,需要的朋友可以參考下

首先,直接上代碼:

import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import com.baomidou.mybatisplus.core.toolkit.DateUtils;
import com.xxxxx.blade.redis.BladeRedis; // 根據(jù)實際包路徑調(diào)整
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import com.xxxxx.common.exception.ServiceException; // 根據(jù)實際包路徑調(diào)整

/**
 * 通用編號生成工具類
 * 功能:生成格式為【業(yè)務(wù)編碼+日期+3位自增序號】的唯一編號(例如:JJ20250826001)
 * 特性:基于Redis實現(xiàn)分布式自增,通過Redisson分布式鎖保證并發(fā)安全,序號按日期重置
 */
@Slf4j // Lombok注解,自動注入日志對象log
@Component // Spring組件注解,將該類注冊為Bean,交由Spring容器管理
public class CommonNumber {

    /**
     * Redis操作客戶端(靜態(tài)變量)
     * 用于執(zhí)行自增、過期時間設(shè)置等Redis命令
     */
    private static BladeRedis BLADE_REDIS;

    /**
     * Redisson客戶端(靜態(tài)變量)
     * 用于獲取分布式鎖,保證多實例環(huán)境下的并發(fā)安全
     */
    private static RedissonClient REDISSSON_CLIENT;

    /**
     * Redisson客戶端(實例變量)
     * 由Spring容器注入,通過@Resource注解按名稱匹配
     */
    @Resource
    private RedissonClient RedissonClient;

    /**
     * Redis操作客戶端(實例變量)
     * 由Spring容器注入,Blade框架封裝的Redis客戶端
     */
    @Resource
    private BladeRedis bladeRedis;

    /**
     * 初始化方法(PostConstruct注解)
     * 作用:在Spring Bean初始化完成后,將實例變量賦值給靜態(tài)變量
     * 原因:工具方法為static,無法直接注入Spring Bean,通過該方式間接獲取容器中的Bean實例
     */
    @PostConstruct
    public void init() {
        BLADE_REDIS = bladeRedis;
        REDISSSON_CLIENT = RedissonClient;
    }

    /**
     * 生成通用唯一編號
     * 格式:業(yè)務(wù)編碼(code) + 年月日(yyyyMMdd) + 3位自增序號(不足補0)
     * 示例:code=JJ → JJ20250826001、JJ20250826002...
     *
     * @param code 業(yè)務(wù)編碼(區(qū)分不同業(yè)務(wù)場景的編號前綴)
     * @return 格式化后的唯一編號
     * @throws ServiceException 當(dāng)獲取分布式鎖失敗或Redis操作異常時拋出
     */
    public static String getCommonNumber(String code) {
        // 1. 定義分布式鎖key:按業(yè)務(wù)編碼區(qū)分,避免不同業(yè)務(wù)鎖競爭
        RLock lock = REDISSSON_CLIENT.getLock("common-number-lock:" + code);

        try {
            // 2. 嘗試獲取分布式鎖:最多等待3秒,持有鎖5秒(防止死鎖)
            // tryLock返回false表示獲取鎖失?。úl(fā)過高)
            if (!lock.tryLock(3, 5, TimeUnit.SECONDS)) {
                throw new ServiceException("系統(tǒng)繁忙,請稍后重試");
            }

            // 3. 格式化當(dāng)前日期為yyyyMMdd格式(用于序號按日期重置)
            String currentTime = DateUtils.format(new Date(), "yyyyMMdd");

            // 4. 定義Redis自增key:業(yè)務(wù)編碼+日期,確保每天的序號從1開始
            String companyNumberKey = "common_number_key:" + code + currentTime;

            // 5. Redis自增操作:原子性遞增,保證序號唯一(初始值為1,每次+1)
            Long incr = BLADE_REDIS.incr(companyNumberKey);

            // 6. 拼接最終編號:業(yè)務(wù)編碼 + 日期 + 3位補0序號(例如:1→001,10→010,100→100)
            String companyNumber = code + currentTime + String.format("%03d", incr);

            // 7. 設(shè)置Rediskey過期時間:48小時(確保過期數(shù)據(jù)自動清理,節(jié)省Redis空間)
            BLADE_REDIS.expire(companyNumberKey, 60 * 60 * 48L);

            // 8. 返回生成的編號
            return companyNumber;

        } catch (InterruptedException e) {
            // 捕獲線程中斷異常(獲取鎖過程中線程被中斷)
            log.error("獲取編號時線程被中斷,code:{}", code, e);
            throw new ServiceException("獲取編號失敗");
        } catch (ServiceException e) {
            // 拋出獲取鎖失敗的自定義異常(無需額外日志,已在拋出時明確)
            throw e;
        } catch (Exception e) {
            // 捕獲其他異常(Redis操作失敗等)
            log.error("獲取編號失敗,code:{}", code, e);
            throw new ServiceException("獲取編號失敗");
        } finally {
            // 9. 釋放分布式鎖:必須在finally中執(zhí)行,確保鎖一定會釋放
            // 先判斷當(dāng)前線程是否持有鎖,避免釋放其他線程的鎖
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }
}

```java

這是一個 基于Redis實現(xiàn)的分布式唯一編號生成工具類,核心功能是生成格式為 業(yè)務(wù)編碼+日期+3位自增序號(如 JJ20250826001)的全局唯一編號,適用于分布式系統(tǒng)中需要有序、不重復(fù)編號的場景(如訂單號、單據(jù)號等)。以下是詳細(xì)解析:

一、類結(jié)構(gòu)與依賴說明

1. 核心注解

  • @Slf4j:Lombok注解,自動生成日志對象 log,用于打印異常日志。
  • @Component:Spring注解,將該類注冊為Spring容器中的Bean,支持依賴注入。

2. 依賴組件

  • BladeRedis:bladex框架封裝的Redis操作工具(類似Spring Data Redis),用于執(zhí)行incr(自增)、expire(設(shè)置過期時間)等Redis命令。
  • RedissonClient:Redisson框架的客戶端,用于操作Redis分布式鎖(解決分布式環(huán)境下的并發(fā)沖突)。
  • @Resource:Spring依賴注入注解,用于注入RedissonClientBladeRedis實例。
  • @PostConstruct:Spring生命周期注解,在Bean初始化完成后執(zhí)行init方法,將注入的實例賦值給靜態(tài)變量(因為getCommonNumber是靜態(tài)方法,無法直接使用非靜態(tài)成員變量)。

二、核心邏輯:編號生成流程

1. 方法定義

public static String getCommonNumber(String code)
  • 入?yún)?code:業(yè)務(wù)編碼(如JJ代表某種單據(jù)類型),用于區(qū)分不同業(yè)務(wù)場景的編號。
  • 出參:格式為 code + 日期(yyyyMMdd) + 3位自增序號 的唯一編號。

2. 關(guān)鍵步驟(帶并發(fā)安全保障)

(1)分布式鎖獲取

RLock lock = REDISSSON_CLIENT.getLock("common-number-lock:"+code);
if (!lock.tryLock(3, 5, TimeUnit.SECONDS)) {
    throw new ServiceException("系統(tǒng)繁忙,請稍后重試");
}
  • 鎖key設(shè)計common-number-lock: + 業(yè)務(wù)編碼code,確保不同業(yè)務(wù)的鎖相互隔離,避免鎖競爭加劇。
  • 鎖參數(shù)
    • 最多等待3秒(waitTime=3):線程獲取鎖時,最多等待3秒,超過則認(rèn)為獲取失敗。
    • 鎖持有時間5秒(leaseTime=5):即使線程未主動釋放鎖,5秒后Redis也會自動釋放,避免死鎖。
  • 作用:解決分布式環(huán)境下的并發(fā)沖突,確保同一業(yè)務(wù)編碼的自增序號不會重復(fù)。

(2)Redis自增生成序號

// 1. 生成當(dāng)天日期(格式:yyyyMMdd)
String currentTime = DateUtil.format(DateUtil.date(), "yyyyMMdd");
// 2. 構(gòu)建Redis自增key(業(yè)務(wù)編碼+日期,確保每天的序號獨立重置)
String companyNumberKey = "common_number_key:" + code + currentTime;
// 3. Redis自增(原子操作,確保序號唯一)
Long incr = BLADE_REDIS.incr(companyNumberKey);
// 4. 序號補零(3位,不足3位前面補0,如1→001,10→010)
String seq = String.format("%03d", incr);
  • Redis key設(shè)計common_number_key: + 業(yè)務(wù)編碼code + 日期currentTime,確保:
    • 不同業(yè)務(wù)編碼的序號相互獨立;
    • 同一業(yè)務(wù)編碼每天的序號從1開始重置(因為日期變化后key會變化)。
  • 原子性保障:Redis的incr命令是原子操作,即使多個線程同時調(diào)用,也能保證自增結(jié)果唯一,無需額外加鎖(但此處仍加分布式鎖是為了避免極端情況下的并發(fā)問題,或配合序號補零等邏輯)。

(3)設(shè)置Redis key過期時間

BLADE_REDIS.expire(companyNumberKey, 60 * 60 * 48L); // 48小時過期
  • 自增key的過期時間設(shè)置為48小時,原因:
    • 確保當(dāng)天的序號能正常自增(當(dāng)天內(nèi)key未過期);
    • 避免Redis中存儲大量過期的自增key,節(jié)省存儲空間;
    • 48小時覆蓋跨天場景(如凌晨23:59生成的key,到次日仍可正常使用,避免提前過期)。

(4)組裝最終編號

String companyNumber = code + currentTime + seq;
  • 例如:業(yè)務(wù)編碼JJ + 日期20250826 + 序號001 → 最終編號JJ20250826001。

3. 異常處理與鎖釋放

try {
    // 編號生成邏輯...
} catch (Exception e) {
    log.error("獲取編號失敗", e); // 打印異常堆棧,便于排查
    throw new ServiceException("獲取編號失敗"); // 拋出自定義業(yè)務(wù)異常,上層處理
} finally {
    // 確保鎖一定釋放(避免死鎖)
    if (lock.isHeldByCurrentThread()) {
        lock.unlock();
    }
}
  • finally塊釋放鎖:無論生成編號成功與否,都要釋放分布式鎖,避免鎖資源泄露。
  • 鎖持有判斷lock.isHeldByCurrentThread() 確保當(dāng)前線程確實持有鎖時才釋放,避免釋放其他線程的鎖(如線程等待鎖超時后,未持有鎖卻執(zhí)行解鎖操作)。

三、核心設(shè)計亮點

1. 分布式并發(fā)安全

  • 雙重保障:Redisincr原子操作 + Redisson分布式鎖,確保序號唯一,無并發(fā)沖突。
  • 鎖自動過期:避免因線程異常導(dǎo)致的死鎖問題。

2. 序號合理性

  • 按天重置:每天的序號從1開始,編號可讀性強(通過編號可直接看出日期)。
  • 固定長度:3位序號補零,確保編號長度一致(便于存儲和展示)。

3. 資源優(yōu)化

  • Redis key過期:48小時自動清理,避免Redis存儲冗余數(shù)據(jù)。
  • 鎖粒度細(xì):按業(yè)務(wù)編碼分鎖,減少鎖競爭,提高并發(fā)效率。

四、潛在問題與優(yōu)化建議

1. 潛在問題

  • 鎖競爭風(fēng)險:如果同一業(yè)務(wù)編碼的并發(fā)請求極高,分布式鎖可能成為性能瓶頸(線程需等待3秒)。
  • Redis依賴風(fēng)險:Redis服務(wù)不可用時,編號生成會失?。o降級方案)。
  • 序號溢出:3位序號最大支持999,如果單日同一業(yè)務(wù)編碼的編號超過999,會生成code+日期+1000(如JJ202508261000),破壞3位固定長度格式。

2. 優(yōu)化建議

  • 優(yōu)化鎖策略
    • 去掉分布式鎖(Redisincr已保證原子性),僅在需要序號補零、特殊邏輯時加鎖,提高并發(fā)效率。
    • 調(diào)整鎖等待時間和持有時間(根據(jù)業(yè)務(wù)并發(fā)量動態(tài)調(diào)整)。
  • 降級方案
    • 當(dāng)Redis不可用時,可臨時使用本地緩存(如AtomicLong)+ 機器標(biāo)識生成編號,避免服務(wù)不可用。
  • 序號擴容
    • 將3位序號改為4位(%04d),支持單日9999個編號,滿足更高并發(fā)場景。
  • 防止重復(fù)生成
    • 可將生成的編號存入Redis或數(shù)據(jù)庫,做最終去重校驗(極端情況下Redis自增失敗時兜底)。
  • 靜態(tài)成員變量優(yōu)化
    • 目前通過@PostConstruct給靜態(tài)變量賦值,依賴Spring初始化順序,可改為使用@Autowired + 非靜態(tài)方法(去掉static),更符合Spring依賴注入規(guī)范(需將工具類注入使用,而非直接調(diào)用靜態(tài)方法)。

五、使用場景

適用于分布式系統(tǒng)中需要生成 有序、唯一、可讀 編號的場景,例如:

  • 訂單編號、支付單號、物流單號;
  • 單據(jù)編號(如入庫單、出庫單);
  • 業(yè)務(wù)流水號等。

總結(jié)

該工具類基于Redis的原子自增和Redisson的分布式鎖,實現(xiàn)了分布式環(huán)境下的唯一編號生成,設(shè)計簡潔、實用性強,同時也存在一些可優(yōu)化的細(xì)節(jié)(如鎖策略、降級方案),可根據(jù)實際業(yè)務(wù)場景調(diào)整。

以上就是基于Redis實現(xiàn)的分布式唯一編號生成工具類的詳細(xì)內(nèi)容,更多關(guān)于Redis分布式唯一編號生成工具類的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Redis鍵值設(shè)計的具體實現(xiàn)

    Redis鍵值設(shè)計的具體實現(xiàn)

    本文主要介紹了Redis鍵值設(shè)計的具體實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-06-06
  • SpringSession+Redis實現(xiàn)集群會話共享的方法

    SpringSession+Redis實現(xiàn)集群會話共享的方法

    為了保證WEB應(yīng)用的承載能力, 需要對WEB應(yīng)用進(jìn)行集群處理.這篇文章主要介紹了SpringSession+Redis實現(xiàn)集群會話共享的方法,需要的朋友參考下吧
    2018-08-08
  • Redis中的List結(jié)構(gòu)從使用到原理分析

    Redis中的List結(jié)構(gòu)從使用到原理分析

    本文詳解Redis List結(jié)構(gòu),涵蓋其基本操作、內(nèi)部實現(xiàn)(ziplist、linkedlist、quicklist)、應(yīng)用場景(消息隊列、動態(tài)排行、歷史記錄)及性能優(yōu)化策略,如配置參數(shù)、批量操作,幫助開發(fā)者高效使用
    2025-09-09
  • Redis刪除緩存失敗的原因和解決方案

    Redis刪除緩存失敗的原因和解決方案

    本文討論了數(shù)據(jù)庫操作成功但緩存刪除失敗時,線上環(huán)境下的應(yīng)對策略,提出了一種更穩(wěn)定的方法,包括主流程寫庫后再刪除緩存、刪除失敗進(jìn)入重試隊列、超過重試上限進(jìn)入死信隊列并觸發(fā)告警和補償?shù)却胧?需要的朋友可以參考下
    2026-04-04
  • 使用Redis實現(xiàn)秒殺功能的簡單方法

    使用Redis實現(xiàn)秒殺功能的簡單方法

    這篇文章主要給大家介紹了關(guān)于使用Redis實現(xiàn)秒殺功能的簡單方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • 簡介Lua腳本與Redis數(shù)據(jù)庫的結(jié)合使用

    簡介Lua腳本與Redis數(shù)據(jù)庫的結(jié)合使用

    這篇文章主要介紹了簡介Lua腳本與Redis數(shù)據(jù)庫的結(jié)合使用,Redis是基于主存的高性能數(shù)據(jù)庫,需要的朋友可以參考下
    2015-06-06
  • Redis和Lua實現(xiàn)分布式限流器的方法詳解

    Redis和Lua實現(xiàn)分布式限流器的方法詳解

    這篇文章主要給大家介紹了關(guān)于Redis和Lua實現(xiàn)分布式限流器的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Redis和Lua具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06
  • Win10下通過Ubuntu安裝Redis的過程

    Win10下通過Ubuntu安裝Redis的過程

    這篇文章主要介紹了Win10下通過Ubuntu安裝Redis,在安裝Ubuntu需要先打開Windows功能,接著創(chuàng)建一個用戶及密碼,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-04-04
  • Redis分布式鎖及安全問題解決

    Redis分布式鎖及安全問題解決

    在分布式環(huán)境中,遇到搶購等訪問共享資源的場景時,需要我們有一種鎖機制去解決并發(fā)問題,本文主要介紹了Redis分布式鎖及安全問題解決,具有一定的參考價值,感興趣的可以了解一下
    2024-03-03
  • 淺析Redis底層數(shù)據(jù)結(jié)構(gòu)Dict

    淺析Redis底層數(shù)據(jù)結(jié)構(gòu)Dict

    Redis是一個鍵值型的數(shù)據(jù)庫,我們可以根據(jù)鍵實現(xiàn)快速的增刪改查,而鍵與值的映射關(guān)系正是通過Dict來實現(xiàn)的,當(dāng)然?Dict?也是?Set?Hash?的實現(xiàn)方式,本文就詳細(xì)帶大家介紹一下Redis底層數(shù)據(jù)結(jié)構(gòu)?Dict,,需要的朋友可以參考下
    2023-05-05

最新評論

盈江县| 常山县| 德惠市| 江川县| 黄大仙区| 万载县| 秭归县| 伽师县| 汉阴县| 蒲城县| 牙克石市| 德化县| 垣曲县| 曲麻莱县| 新晃| 万宁市| 汉寿县| 太仓市| 沁水县| 大理市| 政和县| 英吉沙县| 江华| 綦江县| 肇东市| 双桥区| 长子县| 郁南县| 抚宁县| 高青县| 花莲市| 静安区| 绥阳县| 上蔡县| 大田县| 沐川县| 阿巴嘎旗| 巫溪县| 甘谷县| 黄梅县| 宝兴县|