" />

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

SQLServer中生成雪花ID(Snowflake?ID)的實現(xiàn)方法

 更新時間:2025年08月08日 08:28:06   作者:全棧小5  
這篇文章主要介紹了在SQL?Server中生成雪花ID(Snowflake?ID)的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

前言

在我的印象中用到這個雪花ID比較少,可能是我接觸的大型項目或者開源項目比較少,同時接觸到中大型分布式也比較少,基本都是自研系統(tǒng),用的是自增ID和GuidValue作為唯一編號。
最近項目上使用了一套第三方框架代碼,使用了雪花ID作為表的唯一主鍵,并且之前表沒有這個字段,需要進行表遷移的同時初始化雪花ID字段值。
因此,趁這次機會簡單總結(jié)下雪花ID以及在Sql Server上如何生成雪花ID。

認(rèn)識雪花ID

雪花ID是Twitter開發(fā)的一種分布式唯一ID生成算法,主要用于在分布式系統(tǒng)中生成全局唯一的ID標(biāo)識符。它的名稱來源于"自然界中沒有兩片完全相同的雪花"這一概念,象征著每個生成的ID都是獨一無二的。

雪花ID的核心特點

  1. 全局唯一性:在分布式系統(tǒng)中生成的ID不會重復(fù)
  2. 時間有序性:ID按照時間順序遞增
  3. 高性能:本地生成,不依賴數(shù)據(jù)庫等外部系統(tǒng)
  4. 可解析:ID中包含的信息可以被解析出來

雪花ID的結(jié)構(gòu)(64位)

標(biāo)準(zhǔn)的雪花ID由以下三部分組成(共64位):

| 1位符號位 | 41位時間戳 | 10位工作節(jié)點ID | 12位序列號 |

具體分解:

  1. 符號位(1位):始終為0,保證ID為正數(shù)
  2. 時間戳(41位):毫秒級的時間戳,可以使用約69年
    • 通常從自定義紀(jì)元開始計算(如Twitter使用2010-11-04 01:42:54 UTC)
  3. 工作節(jié)點ID(10位)
    • 通常分為5位數(shù)據(jù)中心ID + 5位機器ID
    • 最多支持32個數(shù)據(jù)中心,每個數(shù)據(jù)中心32臺機器
  4. 序列號(12位):同一毫秒內(nèi)的序列號,支持每毫秒生成4096個ID

雪花ID的優(yōu)勢

  1. 分布式友好:不同節(jié)點可以獨立生成ID而不需要協(xié)調(diào)
  2. 時間有序:生成的ID按時間遞增,有利于數(shù)據(jù)庫索引
  3. 高性能:本地生成,不依賴網(wǎng)絡(luò)或數(shù)據(jù)庫
  4. 信息豐富:ID本身包含時間、節(jié)點等信息

雪花ID的局限性

  1. 時鐘依賴:嚴(yán)重依賴系統(tǒng)時鐘,時鐘回撥會導(dǎo)致ID重復(fù)
  2. 節(jié)點ID配置:需要手動或通過外部系統(tǒng)分配節(jié)點ID
  3. 時間耗盡:41位時間戳大約69年后會耗盡

雪花ID的應(yīng)用場景

  1. 分布式系統(tǒng)主鍵生成
  2. 訂單號、交易號等業(yè)務(wù)編號
  3. 日志跟蹤ID
  4. 任何需要全局唯一且有序ID的場景

示例ID解析

假設(shè)一個雪花ID:123456789012345678

轉(zhuǎn)換為二進制后可以解析出:

  • 時間戳部分:可以轉(zhuǎn)換為具體的生成時間
  • 工作節(jié)點部分:知道是在哪個數(shù)據(jù)中心哪臺機器生成的
  • 序列號部分:知道這是該毫秒內(nèi)生成的第幾個ID

雪花ID因其簡單高效的特性,已經(jīng)成為分布式系統(tǒng)ID生成的經(jīng)典解決方案之一。

生成雪花ID

雪花ID是Twitter提出的一種分布式ID生成算法,它生成64位的唯一ID,通常包含時間戳、工作節(jié)點ID和序列號。
在SQL Server中可以通過以下幾種方式實現(xiàn)雪花ID的生成:

使用T-SQL函數(shù)實現(xiàn)

-- 創(chuàng)建配置表
CREATE TABLE SnowflakeConfig (
    MachineId BIGINT NOT NULL,
    DatacenterId BIGINT NOT NULL,
    LastTimestamp BIGINT NOT NULL,
    Sequence BIGINT NOT NULL,
    CONSTRAINT PK_SnowflakeConfig PRIMARY KEY (MachineId, DatacenterId)
);
-- 初始化配置 (機器ID和數(shù)據(jù)中心ID需要在每個節(jié)點上配置不同)
INSERT INTO SnowflakeConfig (MachineId, DatacenterId, LastTimestamp, Sequence)
VALUES (1, 1, 0, 0);
-- 創(chuàng)建獲取當(dāng)前時間戳的函數(shù)
CREATE FUNCTION GetCurrentTimestamp()
RETURNS BIGINT
AS
BEGIN
    DECLARE @epoch DATETIME2 = '1970-01-01 00:00:00';
    DECLARE @now DATETIME2 = SYSUTCDATETIME();
    RETURN CAST(DATEDIFF_BIG(MILLISECOND, @epoch, @now) AS BIGINT);
END;
-- 創(chuàng)建等待下一毫秒的函數(shù)
CREATE FUNCTION TilNextMillis(@lastTimestamp BIGINT)
RETURNS BIGINT
AS
BEGIN
    DECLARE @timestamp BIGINT;
    SET @timestamp = dbo.GetCurrentTimestamp();
    
    WHILE @timestamp <= @lastTimestamp
    BEGIN
        SET @timestamp = dbo.GetCurrentTimestamp();
    END
    
    RETURN @timestamp;
END;
GO
-- 創(chuàng)建計算冪的函數(shù)(替代位移操作)
CREATE FUNCTION PowerOfTwo(@exponent BIGINT)
RETURNS BIGINT
AS
BEGIN
    RETURN CAST(POWER(CAST(2 AS FLOAT), @exponent) AS BIGINT);
END;
GO
-- 創(chuàng)建生成雪花ID的存儲過程
CREATE PROCEDURE GenerateSnowflakeId
    @MachineId BIGINT = 1,
    @DatacenterId BIGINT = 1,
    @SnowflakeId BIGINT OUTPUT
AS
BEGIN
    SET NOCOUNT ON;
    
    -- 常量定義
    DECLARE @Twepoch BIGINT = 1700058600000;
    DECLARE @MachineIdBits BIGINT = 5;
    DECLARE @DatacenterIdBits BIGINT = 5;
    DECLARE @SequenceBits BIGINT = 12;
    
    -- 使用POWER計算替代位移
    DECLARE @MaxMachineId BIGINT = dbo.PowerOfTwo(@MachineIdBits) - 1;
    DECLARE @MaxDatacenterId BIGINT = dbo.PowerOfTwo(@DatacenterIdBits) - 1;
    DECLARE @SequenceMask BIGINT = dbo.PowerOfTwo(@SequenceBits) - 1;
    
    DECLARE @MachineIdShift BIGINT = @SequenceBits;
    DECLARE @DatacenterIdShift BIGINT = @SequenceBits + @MachineIdBits;
    DECLARE @TimestampLeftShift BIGINT = @SequenceBits + @MachineIdBits + @DatacenterIdBits;
    
    -- 驗證參數(shù)
    IF @MachineId > @MaxMachineId OR @MachineId < 0
    BEGIN
        THROW 50000, 'MachineId can''t be greater than maxMachineId or less than 0', 1;
        RETURN;
    END
    
    IF @DatacenterId > @MaxDatacenterId OR @DatacenterId < 0
    BEGIN
        THROW 50000, 'DatacenterId can''t be greater than maxDatacenterId or less than 0', 1;
        RETURN;
    END
    
    -- 使用事務(wù)確保原子性
    BEGIN TRANSACTION;
    
    BEGIN TRY
        DECLARE @LastTimestamp BIGINT;
        DECLARE @Sequence BIGINT;
        DECLARE @Timestamp BIGINT;
        
        -- 獲取當(dāng)前狀態(tài)
        SELECT @LastTimestamp = LastTimestamp, @Sequence = Sequence
        FROM SnowflakeConfig WITH (UPDLOCK)
        WHERE MachineId = @MachineId AND DatacenterId = @DatacenterId;
        
        -- 獲取當(dāng)前時間戳
        SET @Timestamp = dbo.GetCurrentTimestamp();
        
        -- 檢查時鐘回撥
        IF @Timestamp < @LastTimestamp
        BEGIN
            ROLLBACK TRANSACTION;
            THROW 50000, 'Clock moved backwards. Refusing to generate id', 1;
            RETURN;
        END
        
        -- 同一毫秒內(nèi)生成多個ID
        IF @LastTimestamp = @Timestamp
        BEGIN
            SET @Sequence = (@Sequence + 1) & @SequenceMask;
            IF @Sequence = 0
            BEGIN
                -- 序列耗盡,等待下一毫秒
                SET @Timestamp = dbo.TilNextMillis(@LastTimestamp);
            END
        END
        ELSE
        BEGIN
            SET @Sequence = 0;
        END
        
        -- 更新狀態(tài)
        UPDATE SnowflakeConfig
        SET LastTimestamp = @Timestamp,
            Sequence = @Sequence
        WHERE MachineId = @MachineId AND DatacenterId = @DatacenterId;
        
        -- 生成ID (使用乘法替代位移)
        SET @SnowflakeId = 
            (@Timestamp - @Twepoch) * dbo.PowerOfTwo(@TimestampLeftShift) +
            @DatacenterId * dbo.PowerOfTwo(@DatacenterIdShift) +
            @MachineId * dbo.PowerOfTwo(@MachineIdShift) +
            @Sequence;
        
        COMMIT TRANSACTION;
    END TRY
    BEGIN CATCH
        ROLLBACK TRANSACTION;
        THROW;
    END CATCH
END;
GO

查看效果

-- 使用存儲過程版本
DECLARE @Id BIGINT;
EXEC GenerateSnowflakeId @MachineId = 1, @DatacenterId = 1, @SnowflakeId = @Id OUTPUT;
SELECT @Id AS SnowflakeId;

到此這篇關(guān)于SQLServer中生成雪花ID(Snowflake ID)的實現(xiàn)方法的文章就介紹到這了,更多相關(guān)sqlserver生成雪花id內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

朝阳市| 临西县| 西吉县| 嵊州市| 搜索| 奉节县| 禹州市| 报价| 南漳县| 遵化市| 察隅县| 绥棱县| 咸宁市| 赤城县| 庆云县| 乌苏市| 丰县| 叙永县| 当阳市| 江津市| 广平县| 怀化市| 和平县| 葵青区| 商都县| 松滋市| 淮阳县| 连平县| 新化县| 皋兰县| 达拉特旗| 山丹县| 中超| 基隆市| 民丰县| 英吉沙县| 盐池县| 教育| 九龙城区| 临泽县| 望谟县|