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

SpringBoot基于Redis實(shí)現(xiàn)生成全局唯一ID的方法

 更新時(shí)間:2023年12月21日 09:30:28   作者:在下小吉.  
在項(xiàng)目中生成全局唯一ID有很多好處,生成全局唯一ID有助于提高系統(tǒng)的可用性、數(shù)據(jù)的完整性和安全性,同時(shí)也方便數(shù)據(jù)的管理和分析,所以本文給大家介紹了SpringBoot基于Redis實(shí)現(xiàn)生成全局唯一ID的方法,文中有詳細(xì)的代碼講解,需要的朋友可以參考下

生成全局唯一ID

是一種在分布式系統(tǒng)下用來生成全局唯一id的工具

請(qǐng)?zhí)砑訄D片描述

在項(xiàng)目中生成全局唯一ID有很多好處,其中包括:

  • 數(shù)據(jù)庫主鍵:在數(shù)據(jù)庫中,唯一ID可以作為主鍵,確保每條記錄的唯一性,便于快速檢索和更新數(shù)據(jù)。
  • 分布式系統(tǒng):在分布式系統(tǒng)中,生成全局唯一ID可以避免不同節(jié)點(diǎn)生成相同的ID,確保整個(gè)系統(tǒng)的數(shù)據(jù)一致性。
  • 日志追蹤:在日志系統(tǒng)中,給每條日志分配唯一ID可以方便進(jìn)行日志的追蹤和分析。
  • 安全性:某些場(chǎng)景下,需要對(duì)數(shù)據(jù)進(jìn)行加密或者數(shù)據(jù)權(quán)限控制,唯一ID可以作為安全機(jī)制的一部分。
  • 緩存鍵值:在緩存系統(tǒng)中,使用唯一ID作為鍵值可以避免不同數(shù)據(jù)之間的沖突。
  • 數(shù)據(jù)分片:在分布式存儲(chǔ)系統(tǒng)中,唯一ID可以作為數(shù)據(jù)分片的標(biāo)識(shí),便于數(shù)據(jù)的存儲(chǔ)和查詢。

總之,生成全局唯一ID有助于提高系統(tǒng)的可用性、數(shù)據(jù)的完整性和安全性,同時(shí)也方便數(shù)據(jù)的管理和分析。因此,在許多項(xiàng)目中都會(huì)需要生成全局唯一ID來滿足系統(tǒng)的需求。

為什么要生成全局唯一id

生成全局唯一ID的主要目的是確保系統(tǒng)中的實(shí)體(如對(duì)象、記錄、消息等)具有唯一性標(biāo)識(shí)。以下是一些常見的原因:

  • 數(shù)據(jù)唯一性:全局唯一ID可以確保在系統(tǒng)中每個(gè)實(shí)體都有一個(gè)獨(dú)一無二的標(biāo)識(shí)符,避免數(shù)據(jù)沖突和重復(fù)。
  • 數(shù)據(jù)庫索引:全局唯一ID通常用作數(shù)據(jù)庫表的主鍵或索引,以提高數(shù)據(jù)查詢和檢索的效率。
  • 分布式系統(tǒng):在分布式系統(tǒng)中,各個(gè)節(jié)點(diǎn)可能同時(shí)生成ID,為了避免ID的沖突,需要使用全局唯一ID算法確保整個(gè)系統(tǒng)中的ID唯一性。
  • 數(shù)據(jù)跟蹤與關(guān)聯(lián):通過給實(shí)體分配唯一ID,可以輕松追蹤和關(guān)聯(lián)數(shù)據(jù),例如日志記錄、事務(wù)管理、審計(jì)等。
  • 安全性和權(quán)限控制:全局唯一ID可以用于確保數(shù)據(jù)的安全性和權(quán)限控制,限制對(duì)特定實(shí)體的訪問和操作。
  • 緩存與緩存失效:在緩存系統(tǒng)中,使用全局唯一ID作為緩存鍵,可以確保不同實(shí)體之間的鍵不會(huì)沖突,并且在緩存失效時(shí)能夠正確地重新加載數(shù)據(jù)。

總結(jié)來說,生成全局唯一ID有助于確保數(shù)據(jù)的唯一性、提高系統(tǒng)的可用性和性能,并支持?jǐn)?shù)據(jù)跟蹤、安全性和權(quán)限控制等功能。這在許多系統(tǒng)和應(yīng)用中都是一個(gè)重要的需求。

生成全局id的方法

請(qǐng)?zhí)砑訄D片描述

代碼實(shí)現(xiàn)

ID生成器的算法如下

在這里插入圖片描述

我們要先生成時(shí)間戳,在生成序列號(hào),然后進(jìn)行拼接

package com.hmdp.utils;

import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;

@Component
public class RedisIdWorker {
    /**
     * 開始時(shí)間戳
     */
    private static final long BEGIN_TIMESTAMP = 1640995200L;
    /**
     * 序列號(hào)的位數(shù)
     */
    private static final int COUNT_BITS = 32;

    private StringRedisTemplate stringRedisTemplate;

    public RedisIdWorker(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }

    public long nextId(String keyPrefix) {
        // 1.生成時(shí)間戳
        LocalDateTime now = LocalDateTime.now();
        long nowSecond = now.toEpochSecond(ZoneOffset.UTC);
        long timestamp = nowSecond - BEGIN_TIMESTAMP;

        // 2.生成序列號(hào)
        // 2.1.獲取當(dāng)前日期,精確到天
        String date = now.format(DateTimeFormatter.ofPattern("yyyy:MM:dd"));
        // 2.2.自增長
        long count = stringRedisTemplate.opsForValue().increment("icr:" + keyPrefix + ":" + date);

        // 3.拼接并返回
        return timestamp << COUNT_BITS | count;
    }
}

這段代碼的 timestamp << COUNT_BITS | count;是怎么算出序列號(hào)的

在這里插入圖片描述

在這段代碼中,timestamp << COUNT_BITS | count 是通過位運(yùn)算來生成最終的ID值。

首先,timestamp 是時(shí)間戳,代表了從開始時(shí)間戳到當(dāng)前時(shí)間的秒數(shù)差。COUNT_BITS 是序列號(hào)的位數(shù),這里是32位。

位運(yùn)算符 << 是左移操作符,將 timestamp 的二進(jìn)制表示向左移動(dòng) COUNT_BITS 位,就是將時(shí)間戳占據(jù)高位。這樣做是為了給序列號(hào)騰出足夠的空間。

然后,使用位運(yùn)算符 | 進(jìn)行按位或操作,將左移后的時(shí)間戳與序列號(hào) count 進(jìn)行按位或操作,合并它們的二進(jìn)制表示。

最終得到的結(jié)果就是一個(gè)64位的ID,其中高位是時(shí)間戳部分,低位是序列號(hào)部分。

編寫代碼進(jìn)行測(cè)試

在這里插入圖片描述

package com.hmdp;

import com.hmdp.entity.Shop;
import com.hmdp.service.impl.ShopServiceImpl;
import com.hmdp.utils.CacheClient;
import com.hmdp.utils.RedisIdWorker;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.StringRedisTemplate;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.hmdp.utils.RedisConstants.CACHE_SHOP_KEY;
import static com.hmdp.utils.RedisConstants.SHOP_GEO_KEY;

@SpringBootTest
class HmDianPingApplicationTests {

    @Resource
    private CacheClient cacheClient;

    @Resource
    private ShopServiceImpl shopService;

    @Resource
    private RedisIdWorker redisIdWorker;

		private ExecutorService es = Executors.newFixedThreadPool(500);

    @Test
    void testIdWorker() throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(300);

        Runnable task = () -> {
            for (int i = 0; i < 100; i++) {
                long id = redisIdWorker.nextId("order");
                System.out.println("id = " + id);
            }
            latch.countDown();
        };
        long begin = System.currentTimeMillis();
        for (int i = 0; i < 300; i++) {
            es.submit(task);
        }
        latch.await(); //等待上面的結(jié)束
        long end = System.currentTimeMillis();
        System.out.println("time = " + (end - begin));
    }

    @Test
    void testSaveShop() throws InterruptedException {
        Shop shop = shopService.getById(1L);
        cacheClient.setWithLogicalExpire(CACHE_SHOP_KEY + 1L, shop, 10L, TimeUnit.SECONDS);
    }
}

在技術(shù)的道路上,我們不斷探索、不斷前行,不斷面對(duì)挑戰(zhàn)、不斷突破自我。科技的發(fā)展改變著世界,而我們作為技術(shù)人員,也在這個(gè)過程中書寫著自己的篇章。讓我們攜手并進(jìn),共同努力,開創(chuàng)美好的未來!愿我們?cè)诳萍嫉恼魍旧喜粩鄪^進(jìn),創(chuàng)造出更加美好、更加智能的明天!

以上就是SpringBoot基于Redis實(shí)現(xiàn)生成全局唯一ID的方法的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot Redis全局唯一ID的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 基于StringUtils工具類的常用方法介紹(必看篇)

    基于StringUtils工具類的常用方法介紹(必看篇)

    下面小編就為大家?guī)硪黄赟tringUtils工具類的常用方法介紹(必看篇)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-07-07
  • ocp開閉原則_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    ocp開閉原則_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    這篇文章主要為大家詳細(xì)介紹了ocp開閉原則的相關(guān)資料,ocp開閉原則指導(dǎo)我們?nèi)绾谓⒁粋€(gè)穩(wěn)定的、靈活的系統(tǒng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • Java使用MulticastSocket實(shí)現(xiàn)群聊應(yīng)用程序

    Java使用MulticastSocket實(shí)現(xiàn)群聊應(yīng)用程序

    這篇文章主要為大家詳細(xì)介紹了Java使用MulticastSocket實(shí)現(xiàn)群聊應(yīng)用程序,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • SpringBoot使用榛子云實(shí)現(xiàn)手機(jī)短信發(fā)送驗(yàn)證碼

    SpringBoot使用榛子云實(shí)現(xiàn)手機(jī)短信發(fā)送驗(yàn)證碼

    發(fā)送驗(yàn)證碼主要用于驗(yàn)證用戶手機(jī)的合法性及敏感操作的身份驗(yàn)證,本文使用了SpringBoot實(shí)現(xiàn),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • 【Java】BigDecimal實(shí)現(xiàn)加減乘除運(yùn)算代碼

    【Java】BigDecimal實(shí)現(xiàn)加減乘除運(yùn)算代碼

    本篇文章主要介紹了【Java】BigDecimal實(shí)現(xiàn)加減乘除運(yùn)算代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-02-02
  • 簡(jiǎn)單了解spring cloud 網(wǎng)關(guān)服務(wù)

    簡(jiǎn)單了解spring cloud 網(wǎng)關(guān)服務(wù)

    這篇文章主要介紹了簡(jiǎn)單了解spring cloud 網(wǎng)關(guān)服務(wù),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-10-10
  • 記錄一個(gè)使用Spring?Data?JPA設(shè)置默認(rèn)值的問題

    記錄一個(gè)使用Spring?Data?JPA設(shè)置默認(rèn)值的問題

    這篇文章主要介紹了使用Spring?Data?JPA設(shè)置默認(rèn)值的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • 詳細(xì)分析JAVA 線程池

    詳細(xì)分析JAVA 線程池

    這篇文章主要介紹了JAVA 線程池的的相關(guān)資料,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-06-06
  • 兩行Javascript代碼生成UUID的方法

    兩行Javascript代碼生成UUID的方法

    這篇文章主要介紹了兩行Javascript代碼生成UUID的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • springboot使用@Slf4j進(jìn)行日志的記錄步驟詳解

    springboot使用@Slf4j進(jìn)行日志的記錄步驟詳解

    這篇文章主要介紹了springboot使用@Slf4j進(jìn)行日志的記錄,使用@Slf4j的注解進(jìn)行日志記錄非常方便,本文給大家分享操作步驟,需要的朋友可以參考下
    2023-08-08

最新評(píng)論

乐安县| 黄平县| 吕梁市| 五大连池市| 临澧县| 永宁县| 夏津县| 南靖县| 博野县| 铅山县| 布尔津县| 敖汉旗| 无锡市| 简阳市| 宕昌县| 大洼县| 河南省| 平顶山市| 泾源县| 岢岚县| 肇东市| 鹰潭市| 鹤壁市| 广宁县| 聊城市| 奉化市| 成武县| 清河县| 密山市| 苏尼特左旗| 五寨县| 甘孜县| 富裕县| 镇原县| 盐边县| 博罗县| 平阳县| 永昌县| 麟游县| 上虞市| 金昌市|