成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

簡單實用!利用Redis輕松實現(xiàn)高并發(fā)全局ID生成器

數(shù)據(jù)庫 Redis
今天我就給大家?guī)硪粋€神器級的解決方案——Redis 分布式 ID 生成器!配合 SpringBoot3.0,讓你的 ID 生成變得既簡單又高效。

我相信你會經(jīng)常遇到要生成唯一 ID 的場景,比如標(biāo)識每次請求、生成一個訂單編號、創(chuàng)建用戶需要創(chuàng)建一個用戶 ID。

謝霸戈:這還不簡單,用 UUID 不就行了。

UUID 確實是個好東西,生成的 ID 全球唯一,但是有兩個致命缺陷。

  • 不是遞增的。MySQL 中索引的數(shù)據(jù)結(jié)構(gòu)是 B+Tree,這種數(shù)據(jù)結(jié)構(gòu)的特點是索引樹上的節(jié)點的數(shù)據(jù)是有序的,而如果使用 UUID 作為主鍵,那么每次插入數(shù)據(jù)時,因為無法保證每次產(chǎn)生的 UUID 有序,所以就會出現(xiàn)新的 UUID 需要插入到索引樹的中間去,這樣可能會頻繁地導(dǎo)致頁分裂,使性能下降。
  • 太占用內(nèi)存。每個 UUID 由 36 個字符組成,在字符串進(jìn)行比較時,需要從前往后比較,字符串越長,性能越差。另外字符串越長,占用的內(nèi)存越大,由于頁的大小是固定的,這樣一個頁上能存放的關(guān)鍵字?jǐn)?shù)量就會越少,這樣最終就會導(dǎo)致索引樹的高度越大,在索引搜索的時候,發(fā)生的磁盤 IO 次數(shù)越多,性能越差。

謝霸戈:那咋辦呢?

別急,今天我就給大家?guī)硪粋€神器級的解決方案——Redis 分布式 ID 生成器!配合 SpringBoot3.0,讓你的 ID 生成變得既簡單又高效。

分布式 ID 要滿足什么要求

在進(jìn)入正文前,先介紹下分布式 ID 應(yīng)該滿足哪些特性。

分布式 ID 生成器需要滿足以下特性。

  1. 有序性之單調(diào)遞增,想要分而治之、二分法查找就必須實現(xiàn)。另外,MySQL 是你們用的最多的數(shù)據(jù)庫,B+ 樹為了維護(hù) ID 的有序性,就會頻繁的在索引的中間位置插入而挪動后面節(jié)點的位置,甚至導(dǎo)致頻繁的頁分裂,這對于性能的影響是極大的。
  2. 全局唯一性,ID 不唯一就會出現(xiàn)主鍵沖突。
  3. 高性能,生成 ID 是高頻操作,如果性能緩慢,系統(tǒng)的整體性能都會受到限制。
  4. 高可用,也就是在給定的時間間隔內(nèi),一個系統(tǒng)總的可用時間占的比例。
  5. 存儲空間小,用 MySQL 的 InnoDB B+樹來說,普通索引(非聚集索引)會存儲主鍵值,主鍵越大,每個 Page 頁可以存儲的數(shù)據(jù)就越少,訪問磁盤 I/O 的次數(shù)就會增加。

Redis String 實現(xiàn)分布式 ID

Redis 集群能保證高可用和高性能,為了節(jié)省內(nèi)存,ID 可以使用數(shù)字的形式,并且通過遞增的方式來創(chuàng)建新的 ID。

防止重啟數(shù)據(jù)丟失,你還需要把 Redis AOF 持久化開啟。

MySQL:“開啟 AOF 持久,為了性能設(shè)置成 everysec 策略還是有可能丟失一秒的數(shù)據(jù),所以你還可以使用一個異步機(jī)制將生成的最大 ID 持久化到一個 MySQL。”

好主意,在生成 ID 之后發(fā)送一條消息到 MQ 消息隊列中,把值持久化到 MySQL 中。

我們可以使用 Redis String 數(shù)據(jù)類型來實現(xiàn),key 用于區(qū)分不同業(yè)務(wù)場景的 ID 生成器,value 存儲 ID。

String 數(shù)據(jù)類型提供了 INCR 指令,它能把 key 中存儲的數(shù)字加 1 并返回客戶端。如果 key 不存在,那么 key 的 value 先被初始化成 0,再執(zhí)行加 1 操作并返回給客戶端。

Redis,作為一個高性能的內(nèi)存數(shù)據(jù)庫,天生就適合處理高并發(fā)的場景。它的“單線程”模型更是讓它在處理 ID 生成時如魚得水。

Redis 的操作是原子性的,這就意味著在整個過程中,不會有任何的并發(fā)問題出現(xiàn),從而確保了 ID 的唯一性。

設(shè)計思路

設(shè)計思路如下圖所示。

圖 2-4

  1. 假設(shè)訂單 ID 生成器的 key 是“counter:order”,當(dāng)應(yīng)用服務(wù)啟動的時候先從數(shù)據(jù)庫中查詢出最大值 M。執(zhí)行 EXISTS counter:order 判斷是否存在 key。
  • Redis 中不存在 key “counter:order”,執(zhí)行 SET counter:order M 將 M 值作寫入 Redis。
  • Redis 中存在 key “counter:order”,值為 K,那么就比較 M 和 K 的值,執(zhí)行 SET counter:order max(M, N)將最大值寫入 Redis,相等的話就不操作。
  1. 應(yīng)用服務(wù)啟動完成后,每次需要生成 ID 的時候,應(yīng)用程序就向 Redis 服務(wù)器發(fā)送 INCR counter:order指令。
  2. 應(yīng)用程序?qū)@取到的 ID 值發(fā)送到 MQ 消息隊列,消費者監(jiān)聽隊列把值更新到 MySQL。

SpringBoot 代碼實現(xiàn)

接下來,我們結(jié)合 SpringBoot3.0 來打造一個強大且易用的 Redis 分布式 ID 生成器。

首先,我們需要在 SpringBoot 項目中引入 redis 的依賴。在pom.xml文件中添上這行代碼:

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

搞定依賴后,我們得告訴 SpringBoot 怎么連接到 Redis。打開application.yml文件,填上 Redis 的服務(wù)地址和端口:

spring:
  application:
    name: redis
  redis:
    host: 127.0.0.1
    port: 6379
    password: magebyte
    timeout: 6000

萬事俱備,只欠東風(fēng)!接下來,我們編寫一個 ID 生成器工具類。這個工具類負(fù)責(zé)與 Redis 交互,生成唯一的 ID。這里我們使用 Redis 的INCR命令,它能讓 ID 自增,確保每次獲取的 ID 都是唯一的。

@Component
public class OrderIdGenerator implements InitializingBean {

    private final StringRedisTemplate redisTemplate;

    /**
     * 操作數(shù)據(jù)庫 dao
     */
    private final IdGeneratorMapper idGeneratorMapper;

    private static final String KEY = "counter:order";

    /**
     * 數(shù)據(jù)庫中的 ID 值
     */
    private String dbId;

    @Autowired
    public OrderIdGenerator(StringRedisTemplate redisTemplate, IdGeneratorMapper idGeneratorMapper) {
        this.redisTemplate = redisTemplate;
        this.idGeneratorMapper = idGeneratorMapper;
    }

    public Long generateId(String key) {
        return redisTemplate.opsForValue().increment(key, 1);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        // 從數(shù)據(jù)庫查詢最大 ID
        this.dbId = idGeneratorMapper.getMaxID(KEY);

        Boolean hasKey = redisTemplate.hasKey(KEY);
        if (Boolean.TRUE.equals(hasKey)) {
            // key 存在,比較 dbId 與 redisValue,取出最大值
            String redisValue = redisTemplate.opsForValue().get(KEY);
            String targetValue = max(this.dbId, redisValue);
        } else {

自定義 ID 規(guī)則

不過呢,光有唯一的 ID 還不夠,我們還得讓它更符合業(yè)務(wù)的實際需求。比如訂單編號吧,我們可能希望它的格式是ORD-20240528-0001,其中ORD是業(yè)務(wù)標(biāo)識,20240528是日期,0001是當(dāng)天的序號。

public String generateCustomId(String key, String prefix, String datePattern) {
    long sequence = redisTemplate.opsForValue().increment(key, 1);
    return String.format("%s-%s-%04d", prefix, new SimpleDateFormat(datePattern).format(new Date()), sequence);
}

那具體怎么用呢?讓我們在業(yè)務(wù)代碼中一探究竟!想象一下,在一個電商系統(tǒng)中,當(dāng)一個新的訂單如流星般劃過天際,我們迫不及待地想要一個獨一無二的 ID 來標(biāo)記它時——很簡單,只需調(diào)用我們的generateCustomId方法,傳入訂單相關(guān)的參數(shù)即可。

@Service
public class OrderService {
    private final RedisIdGenerator idGenerator;

    @Autowired
    public OrderService(RedisIdGenerator idGenerator) {
        this.idGenerator = idativeIdGenerator;
    }

    public Order createOrder(OrderRequest request) {
        String orderId = idGenerator.generateCustomId("order:id", "ORD", "yyyyMMdd");
        Order order = new Order();
        order.setId(orderId);
        // 其他業(yè)務(wù)邏輯...
        return order;
    }
}
責(zé)任編輯:姜華 來源: 碼哥跳動
相關(guān)推薦

2022-12-29 08:43:54

IDredis

2017-07-01 16:02:39

分布式ID生成器

2019-12-27 10:00:34

開源技術(shù) 軟件

2022-07-25 10:27:36

背景生成器工具前端

2024-01-26 08:28:41

工單號生成器場景

2022-03-03 08:30:41

GeneratorES6函數(shù)

2025-03-11 08:50:00

CASID分布式

2020-08-21 13:15:29

開發(fā)技能代碼

2022-02-15 10:30:58

UUID

2015-08-25 11:07:58

2025-01-23 08:36:27

CSS開發(fā)工具

2011-12-23 13:42:05

JavaScript

2010-09-07 16:31:17

SQL語句insert

2021-04-22 21:15:38

Generator函數(shù)生成器

2025-01-06 09:06:04

JavaScriptWeb 開發(fā)Generators

2017-03-20 17:49:21

Java Web模板代碼

2016-01-08 10:55:31

PHP莫斯電碼生成器

2016-12-21 10:55:55

PHP莫斯電碼生成器

2021-07-14 07:17:37

Springboot分布式UIDGenerato

2024-11-01 15:51:06

點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 精品欧美乱码久久久久久 | 欧美日韩在线一区 | 国产二区精品视频 | 三级高清 | 五月天婷婷久久 | 色资源站 | 亚洲国产精品va在线看黑人 | 国内精品伊人久久久久网站 | 男女黄网站 | 99精品在线| 国产在线精品一区二区三区 | 天天久| 亚洲国产偷 | 色婷婷综合网 | 日韩a v在线免费观看 | 亚洲国产精品一区二区www | 午夜资源 | 黄色成人在线观看 | 欧美一区二区三区在线 | 亚洲性综合网 | 国产精品一区二区欧美黑人喷潮水 | 亚洲免费婷婷 | 亚洲精品99久久久久久 | 精品久久久网站 | 欧美一区二区三区精品免费 | 国产欧美日韩综合精品一 | 欧美精品欧美精品系列 | 91国内产香蕉| 涩爱av一区二区三区 | 久久一二 | www国产成人免费观看视频 | 日韩视频―中文字幕 | 日韩在线一区二区三区 | 亚洲成人三级 | 一区二区三区免费在线观看 | 亚洲色图婷婷 | 天堂av影院 | 国内精品久久久久久影视8 最新黄色在线观看 | 国产欧美一区二区精品忘忧草 | 日韩精品二区 | 亚洲色图综合 |