亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

基于Redis實現(xiàn)分布式單號及分布式ID(自定義規(guī)則生成)

 更新時間:2021年09月22日 10:39:55   作者:程序員小強  
一些業(yè)務(wù)背景下,業(yè)務(wù)要求單號需要有區(qū)分不同的前綴,那么在分布式的架構(gòu)下如何自定義單號而且還能保證唯一呢?本文就來詳細的介紹一下

背景

一些業(yè)務(wù)背景下,業(yè)務(wù)要求單號需要有區(qū)分不同的前綴,那么在分布式的架構(gòu)下如何自定義單號而且還能保證唯一呢?

注:分布式ID也可以此方式

Redis實現(xiàn)方式

Redis的所有命令操作都是單線程的,本身提供像 incr 和 increby 這樣的自增原子命令,所以能保證生成的 ID 肯定是唯一有序的。

優(yōu)點:不依賴于數(shù)據(jù)庫,靈活方便,且性能優(yōu)于數(shù)據(jù)庫;數(shù)字ID天然排序,對分頁或者需要排序的結(jié)果很有幫助。

缺點:如果系統(tǒng)中沒有Redis,還需要引入新的組件,增加系統(tǒng)復(fù)雜度;需要編碼和配置的工作量比較大。

考慮到單節(jié)點的性能瓶頸,可以使用 Redis 集群來獲取更高的吞吐量。
使用 Redis 集群也可以方式單點故障的問題。

代碼實例

創(chuàng)建常量類

/**
 * 單號生成常量
 *
 * @author mq
 */
public class FormNoConstants {
    /**
     * 單號流水號緩存Key前綴
     */
    public static final String SERIAL_CACHE_PREFIX = "FORM_NO_CACHE_";

    /**
     * 單號流水號yyMMdd前綴
     */
    public static final String SERIAL_YYMMDD_PREFIX = "yyMMdd";

    /**
     * 單號流水號yyyyMMdd前綴
     */
    public static final String SERIAL_YYYYMMDD_PREFIX = "yyyyMMdd";
    
    /**
     * 默認緩存天數(shù)
     */
    public static final int DEFAULT_CACHE_DAYS = 7;
}

單號生成枚舉

注:為了方便擴展,方便復(fù)用,使用枚舉方式,可以自定義枚舉值來生成不同的單號

/**
 * 單號生成類型枚舉
 *
 * @author mq
 * 注:隨機號位于流水號之后,流水號使用redis計數(shù)據(jù),每天都是一個新的key,長度不足時則自動補0
 * <p>
 * 生成規(guī)則 =固定前綴+當(dāng)天日期串+流水號(redis自增,不足長度則補0)+隨機數(shù)
 */
public enum FormNoTypeEnum {

    /**
     * 應(yīng)付單單號:
     * 固定前綴:YF
     * 時間格式:yyyyMMdd
     * 流水號長度:7(當(dāng)單日單據(jù)較多時可根據(jù)業(yè)務(wù)適當(dāng)增加流水號長度)
     * 隨機數(shù)長度:3
     * 總長度:20
     */
    YF_ORDER("YF", FormNoConstants.SERIAL_YYYYMMDD_PREFIX, 7, 3, 20),

    /**
     * 付款單單號:
     * 固定前綴:FK
     * 時間格式:yyyyMMdd
     * 流水號長度:7
     * 隨機數(shù)長度:3
     * 總長度:20
     */
    FK_ORDER("FK", FormNoConstants.SERIAL_YYYYMMDD_PREFIX, 7, 3, 20),

    /**
     * 測試單單號:
     * 固定前綴:""
     * 時間格式:yyyyMMdd
     * 流水號長度:10
     * 隨機數(shù)長度:0
     * 總長度:20
     */
    TEST_ORDER("te", FormNoConstants.SERIAL_YYYYMMDD_PREFIX, 10, 0, 20),
    ;

    /**
     * 單號前綴
     * 為空時填""
     */
    private String prefix;

    /**
     * 時間格式表達式
     * 例如:yyyyMMdd
     */
    private String datePattern;

    /**
     * 流水號長度
     */
    private Integer serialLength;
    /**
     * 隨機數(shù)長度
     */
    private Integer randomLength;

    /**
     * 總長度
     */
    private Integer totalLength;


    FormNoTypeEnum(String prefix, String datePattern, Integer serialLength, Integer randomLength, Integer totalLength) {
        this.prefix = prefix;
        this.datePattern = datePattern;
        this.serialLength = serialLength;
        this.randomLength = randomLength;
        this.totalLength = totalLength;
    }
    //省略 get 方法
}

單號生成工具類

/**
 * 單號生成工具類
 *
 * @author mq
 */
public class FormNoSerialUtil {

    /**
     * 生成單號前綴
     */
    public static String getFormNoPrefix(FormNoTypeEnum formNoTypeEnum) {
        //格式化時間
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(formNoTypeEnum.getDatePattern());
        StringBuffer sb = new StringBuffer();
        sb.append(formNoTypeEnum.getPrefix());
        sb.append(formatter.format(LocalDateTime.now()));
        return sb.toString();
    }
    
    /**
     * 構(gòu)建流水號緩存Key
     *
     * @param serialPrefix 流水號前綴
     * @return 流水號緩存Key
     */
    public static String getCacheKey(String serialPrefix) {
        return FormNoConstants.SERIAL_CACHE_PREFIX.concat(serialPrefix);
    }
    
    /**
     * 補全流水號
     *
     * @param serialPrefix      單號前綴
     * @param incrementalSerial 當(dāng)天自增流水號
     * @author mengqiang
     * @date 2019/1/1
     */
    public static String completionSerial(String serialPrefix, Long incrementalSerial,
                                          FormNoTypeEnum formNoTypeEnum) {
        StringBuffer sb = new StringBuffer(serialPrefix);

        //需要補0的長度=流水號長度 -當(dāng)日自增計數(shù)長度
        int length = formNoTypeEnum.getSerialLength() - String.valueOf(incrementalSerial).length();
        //補零
        for (int i = 0; i < length; i++) {
            sb.append("0");
        }
        //redis當(dāng)日自增數(shù)
        sb.append(incrementalSerial);
        return sb.toString();
    }


    /**
     * 補全隨機數(shù)
     *
     * @param serialWithPrefix 當(dāng)前單號
     * @param formNoTypeEnum   單號生成枚舉
     * @author mengqiang
     * @date 2019/1/1
     */
    public static String completionRandom(String serialWithPrefix, FormNoTypeEnum formNoTypeEnum) {
        StringBuffer sb = new StringBuffer(serialWithPrefix);
        //隨機數(shù)長度
        int length = formNoTypeEnum.getRandomLength();
        if (length > 0) {
            Random random = new Random();
            for (int i = 0; i < length; i++) {
                //十以內(nèi)隨機數(shù)補全
                sb.append(random.nextInt(10));
            }
        }
        return sb.toString();
    }
}

單號生成接口

/**
 * 單號生成接口
 *
 * @author mq
 */
public interface FormNoGenerateService {

    /**
     * 根據(jù)單據(jù)編號類型 生成單據(jù)編號
     *
     * @param formNoTypeEnum 單據(jù)編號類型
     * @author mengqiang
     * @date 2019/1/1
     */
    String generateFormNo(FormNoTypeEnum formNoTypeEnum);
}

單號生成接口實現(xiàn)

/**
 * 單號生成接口實現(xiàn)
 *
 * @author mengqiang
 * @version FormNoGenerateServiceImpl.java, v 1.0 2019-01-01 18:10
 */
@Service
public class FormNoGenerateServiceImpl implements FormNoGenerateService {
    /**
     * redis 服務(wù)
     * demo 項目沒有加redis相關(guān),若有需要請參考,redis的博客
     */
    @Autowired
    private RedisCache redisCache;
    /**
     * 根據(jù)單據(jù)編號類型 生成單據(jù)編號
     *
     * @param formNoTypeEnum 單據(jù)編號類型
     * @author mengqiang
     * @date 2019/1/1
     */
    @Override
    public String generateFormNo(FormNoTypeEnum formNoTypeEnum) {
        //獲得單號前綴
        //格式 固定前綴 +時間前綴 示例 :YF20190101
        String formNoPrefix = FormNoSerialUtil.getFormNoPrefix(formNoTypeEnum);
        //獲得緩存key
        String cacheKey = FormNoSerialUtil.getCacheKey(formNoPrefix);
        //獲得當(dāng)日自增數(shù)
        Long incrementalSerial = redisCache.incr(cacheKey);
        //設(shè)置失效時間 7天
        redisCache.expire(cacheKey, FormNoConstants.DEFAULT_CACHE_DAYS, TimeUnit.DAYS);
        //組合單號并補全流水號
        String serialWithPrefix = FormNoSerialUtil
                .completionSerial(formNoPrefix, incrementalSerial, formNoTypeEnum);
        //補全隨機數(shù)
        return FormNoSerialUtil.completionRandom(serialWithPrefix, formNoTypeEnum);
    }
}

使用測試

在這里插入圖片描述

redis截圖

在這里插入圖片描述

總結(jié)

以上還不是最優(yōu)雅的方式,最好是能做成jar包方式,做成通用的服務(wù)

到此這篇關(guān)于基于Redis實現(xiàn)分布式單號及分布式ID(自定義規(guī)則生成)的文章就介紹到這了,更多相關(guān)基于Redis實現(xiàn)分布式單號及分布式ID(自定義規(guī)則生成)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Redis過期Key刪除策略和內(nèi)存淘汰策略的實現(xiàn)

    Redis過期Key刪除策略和內(nèi)存淘汰策略的實現(xiàn)

    當(dāng)內(nèi)存使用達到上限,就無法存儲更多數(shù)據(jù)了,為了解決這個問題,Redis內(nèi)部會有兩套內(nèi)存回收的策略,過期Key刪除策略和內(nèi)存淘汰策略,本文就來詳細的介紹一下這兩種方法,感興趣的可以了解一下
    2024-02-02
  • redis加鎖的幾種方式匯總

    redis加鎖的幾種方式匯總

    這篇文章主要介紹了redis加鎖的幾種方式匯總,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • Redis如何統(tǒng)計用戶訪問量

    Redis如何統(tǒng)計用戶訪問量

    這篇文章主要介紹了Redis如何統(tǒng)計用戶訪問量問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • 基于Redis實現(xiàn)雙加密Token的示例代碼

    基于Redis實現(xiàn)雙加密Token的示例代碼

    在現(xiàn)代分布式系統(tǒng)中,Token管理是身份驗證和授權(quán)的核心部分,本文將深入分析一個基于Redis的Token管理實現(xiàn),探討其設(shè)計思路、關(guān)鍵代碼邏輯以及實現(xiàn)細節(jié),通過對源碼的逐層剖析,幫助讀者更好地理解Token管理的實現(xiàn)原理,需要的朋友可以參考下
    2025-01-01
  • 深度剖析Redis字符串操作指南從入門到實戰(zhàn)應(yīng)用

    深度剖析Redis字符串操作指南從入門到實戰(zhàn)應(yīng)用

    Redis字符串類型二進制安全,支持文本、數(shù)字、二進制等數(shù)據(jù),涵蓋基礎(chǔ)操作、數(shù)字計算、過期管理及分布式鎖等應(yīng)用,結(jié)合優(yōu)化策略提升系統(tǒng)性能,本文給大家介紹Redis字符串操作指南,感興趣的朋友一起看看吧
    2025-07-07
  • 使用redis實現(xiàn)延遲通知功能(Redis過期鍵通知)

    使用redis實現(xiàn)延遲通知功能(Redis過期鍵通知)

    這篇文章主要介紹了使用redis實現(xiàn)延遲通知功能(Redis過期鍵通知)的相關(guān)知識,本文通過實例代碼圖文相結(jié)合給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2021-09-09
  • redis集群搭建_動力節(jié)點Java學(xué)院整理

    redis集群搭建_動力節(jié)點Java學(xué)院整理

    這篇文章主要介紹了redis集群搭建,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-08-08
  • 淺析PHP分布式中Redis實現(xiàn)Session的方法

    淺析PHP分布式中Redis實現(xiàn)Session的方法

    這篇文章主要介紹了PHP分布式中Redis實現(xiàn)Session的方法,文中詳細介紹了兩種方法的使用方法,并給出了測試的示例代碼,有需要的朋友可以參考借鑒,下面來一起看看吧,
    2016-12-12
  • 使用SpringBoot?+?Redis?實現(xiàn)接口限流的方式

    使用SpringBoot?+?Redis?實現(xiàn)接口限流的方式

    這篇文章主要介紹了SpringBoot?+?Redis?實現(xiàn)接口限流,Redis?除了做緩存,還能干很多很多事情:分布式鎖、限流、處理請求接口冪等,文中給大家提到了限流注解的創(chuàng)建方式,需要的朋友可以參考下
    2022-05-05
  • Redis實現(xiàn)排行榜及相同積分按時間排序功能的實現(xiàn)

    Redis實現(xiàn)排行榜及相同積分按時間排序功能的實現(xiàn)

    這篇文章主要介紹了Redis實現(xiàn)排行榜及相同積分按時間排序,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-08-08

最新評論