欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Redis實現(xiàn)全局唯一Id的使用示例

 更新時間:2023年12月19日 09:13:42   作者:伏加特遇上西柚  
全局唯一ID有多個方法可供選擇,其中一種是使用Redis,本文就來介紹一下Redis實現(xiàn)全局唯一Id的使用示例,具有一定的參考價值,感興趣的可以了解一下

一、全局唯一Id簡介

系統(tǒng)當中有些場景如果使用數(shù)據(jù)庫自增ID就存在一些問題:

  • id的規(guī)律性太明顯
  • 受單表數(shù)據(jù)量的限制

場景分析:如果我們的id具有太明顯的規(guī)則,用戶或者說商業(yè)對手很容易猜測出來我們的一些敏感信息,比如商城在一天時間內,賣出了多少單,這明顯不合適。

場景分析二:隨著我們商城規(guī)模越來越大,mysql的單表的容量不宜超過500W,數(shù)據(jù)量過大之后,我們要進行拆庫拆表,但拆分表了之后,他們從邏輯上講他們是同一張表,所以他們的id是不能一樣的, 于是乎我們需要保證id的唯一性。

全局唯一ID生成策略:

  • UUID
  • Redis自增
  • snowflake算法
  • 數(shù)據(jù)庫自增

Redis自增ID策略:

  • 每天一個key,方便統(tǒng)計訂單量
  • ID構造是 時間戳 + 計數(shù)器

全局ID生成器,是一種在分布式系統(tǒng)下用來生成全局唯一ID的工具,一般要滿足下列特性:

在這里插入圖片描述

為了增加ID的安全性,我們可以不直接使用Redis自增的數(shù)值,而是拼接一些其它信息:

在這里插入圖片描述

D的組成部分:符號位:1bit,永遠為0

時間戳:31bit,以秒為單位,可以使用69年

序列號:32bit,秒內的計數(shù)器,支持每秒產生2^32個不同ID

二、Redis實現(xiàn)全局唯一Id實踐

2.1添加RedisIdWorker配置類

package com.example.idgenerate.config;

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 {
    /**
     * 開始時間戳,此處的時間戳為預生成
     */
    private static final long BEGIN_TIMESTAMP = 1640995200L;
    /**
     * 序列號的位數(shù)
     */
    private static final int COUNT_BITS = 32;

    private StringRedisTemplate stringRedisTemplate;

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

    /**
      * 描述信息: 生成唯一id
      *
      * @date  2023/05/21
      * @param keyPrefix 前綴,用于區(qū)分不同的業(yè)務
      * @return long id
      **/
    public long nextId(String keyPrefix) {
        // 1.生成時間戳
        LocalDateTime now = LocalDateTime.now();
        long nowSecond = now.toEpochSecond(ZoneOffset.UTC);
        long timestamp = nowSecond - BEGIN_TIMESTAMP;

        // 2.生成序列號
        // 2.1.獲取當前日期,精確到天
        String date = now.format(DateTimeFormatter.ofPattern("yyyy:MM:dd"));
        // 2.2.自增長 key格式:icr:order:2023:05:21
        long count = stringRedisTemplate.opsForValue().increment("icr:" + keyPrefix + ":" + date);

        // 3.拼接并返回,目的是讓時間戳存放在32上,序列號在低32位
        return timestamp << COUNT_BITS | count;
    }
}


在這里插入圖片描述

2.2測試類

 @Autowired
    private RedisIdWorker redisIdWorker;

    /**
      * 描述信息:將日期時間轉成秒級數(shù)字
      *
      * @date  2023/05/21
      * @return void
      **/
    @Test
    void contextLoads() {
        LocalDateTime time = LocalDateTime.of(2023, 5, 20, 0, 0,0);
        //將時間轉成秒數(shù)
        long second = time.toEpochSecond(ZoneOffset.UTC);
        System.out.println("second = " + second);
    }
    //實際項目中應使用自定義的線程池
    private ExecutorService es = Executors.newFixedThreadPool(500);

    /**
      * 描述信息: 測試redis生成3w條id所需要的時間
      *
      * @date  2023/05/21
      * @return void
      **/
    @Test
    void testIdWorker() throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(300);

        Runnable task = () -&gt; {
            for (int i = 0; i &lt; 100; i++) {
                long id = redisIdWorker.nextId("order");
                System.out.println("id = " + id);
            }
            latch.countDown();
        };
        long begin = System.currentTimeMillis();
        for (int i = 0; i &lt; 300; i++) {
            es.submit(task);
        }
        latch.await();
        long end = System.currentTimeMillis();
        System.out.println("time = " + (end - begin));
    }

在這里插入圖片描述

知識小貼士:關于countdownlatch

countdownlatch名為信號槍主要的作用是同步協(xié)調在多線程的等待于喚醒問題

我們如果沒有CountDownLatch ,那么由于程序是異步的,當異步程序沒有執(zhí)行完時,主線程就已經執(zhí)行完了,然后我們期望的是分線程全部走完之后,主線程再走,所以我們此時需要使用到CountDownLatch

CountDownLatch 中有兩個最重要的方法
1、countDown
2、await

await 方法是阻塞方法,我們擔心分線程沒有執(zhí)行完時,main線程就先執(zhí)行,所以使用await可以讓main線程阻塞,那么什么時候main線程不再阻塞呢?當CountDownLatch 內部維護的 變量變?yōu)?時,就不再阻塞,直接放行,那么什么時候CountDownLatch 維護的變量變?yōu)? 呢,我們只需要調用一次countDown ,內部變量就減少1,我們讓分線程和變量綁定, 執(zhí)行完一個分線程就減少一個變量,當分線程全部走完,CountDownLatch 維護的變量就是0,此時await就不再阻塞,統(tǒng)計出來的時間也就是所有分線程執(zhí)行完后的時間。

到此這篇關于Redis實現(xiàn)全局唯一Id的使用示例的文章就介紹到這了,更多相關Redis 全局唯一Id內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 基于Redis位圖實現(xiàn)系統(tǒng)用戶登錄統(tǒng)計

    基于Redis位圖實現(xiàn)系統(tǒng)用戶登錄統(tǒng)計

    這篇文章主要介紹了基于Redis位圖實現(xiàn)系統(tǒng)用戶登錄統(tǒng)計,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-11-11
  • Redis高階使用消息隊列分布式鎖排行榜等(高階用法)

    Redis高階使用消息隊列分布式鎖排行榜等(高階用法)

    在大多數(shù)傳統(tǒng)的web系統(tǒng)中,使用Redis一般都是作為緩存使用,在大數(shù)據(jù)查詢時作為緩解性能的一種解決方案,這篇文章主要介紹了Redis高階使用消息隊列分布式鎖排行榜等,需要的朋友可以參考下
    2024-03-03
  • 關于redis可視化工具讀取數(shù)據(jù)亂碼問題

    關于redis可視化工具讀取數(shù)據(jù)亂碼問題

    大家來聊一聊在日常操作redis時用的是什么工具,redis提供的一些命令你都了解了嗎,今天通過本文給大家介紹redis可視化工具讀取數(shù)據(jù)亂碼問題,感興趣的朋友跟隨小編一起看看吧
    2021-07-07
  • Spring?Boot?3.0x的Redis?分布式鎖的概念和原理

    Spring?Boot?3.0x的Redis?分布式鎖的概念和原理

    Redis?分布式鎖是一種基于?Redis?的分布式鎖解決方案,它的原理是利用?Redis?的原子性操作實現(xiàn)鎖的獲取和釋放,從而保證共享資源的獨占性,這篇文章主要介紹了適合?Spring?Boot?3.0x的Redis?分布式鎖,需要的朋友可以參考下
    2024-08-08
  • Redis實現(xiàn)事物以及鎖的方法

    Redis實現(xiàn)事物以及鎖的方法

    本文主要介紹了Redis實現(xiàn)事物以及鎖的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-07-07
  • Redis高并發(fā)分布鎖的示例

    Redis高并發(fā)分布鎖的示例

    在分布式系統(tǒng)中,實現(xiàn)分布式鎖是一項常見的需求,本文主要介紹了Redis高并發(fā)分布鎖的示例 ,具有一定的參考價值,感興趣的可以了解一下
    2024-03-03
  • 利用Redis統(tǒng)計網站在線活躍用戶的方法

    利用Redis統(tǒng)計網站在線活躍用戶的方法

    Redis支持對String類型的value進行基于二進制位的置位操作。通過將一個用戶的id對應value上的一位,通過對活躍用戶對應的位進行置位,就能夠用一個value記錄所有活躍用戶的信息。下面這篇文章主要介紹了利用Redis統(tǒng)計網站在線活躍用戶的方法,需要的朋友可以參考。
    2017-01-01
  • 淺談redis整數(shù)集為什么不能降級

    淺談redis整數(shù)集為什么不能降級

    本文主要介紹了redis整數(shù)集為什么不能降級,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-07-07
  • 詳解Redis中key的命名規(guī)范和值的命名規(guī)范

    詳解Redis中key的命名規(guī)范和值的命名規(guī)范

    這篇文章主要介紹了詳解Redis中key的命名規(guī)范和值的命名規(guī)范,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-12-12
  • Redis事務涉及的watch、multi等命令詳解

    Redis事務涉及的watch、multi等命令詳解

    這篇文章主要介紹了Redis事務涉及的watch、multi等命令,本文給大家介紹的非常詳細,具有一定的參考借鑒價值 ,需要的朋友可以參考下
    2018-10-10

最新評論