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

C#利用雪花算法實現(xiàn)生成ID工具類

 更新時間:2023年12月06日 08:14:58   作者:rjcql  
雪花算法表示生成的ID如雪花般獨一無二,該算法源自Twitter,主要用于解決分布式系統(tǒng)的唯一Id生成問題,本文主要介紹了C#如何利用利用雪花算法實現(xiàn)生成ID,需要的可以參考下

寫在前面

傳說自然界中并不存在兩片完全一樣的雪花的,每一片雪花都擁有自己漂亮獨特的形狀、獨一無二;雪花算法也表示生成的ID如雪花般獨一無二,該算法源自Twitter。

雪花算法主要用于解決分布式系統(tǒng)的唯一Id生成問題,在生產(chǎn)環(huán)境中可以部署一個單獨的服務(wù)來運行雪花算法,然后通過請求該服務(wù)獲取全局Id。

相對于UUID來說,其長度短,生成快,做數(shù)據(jù)庫主鍵時方便建立索引,所以整體效率要高很多。

代碼實現(xiàn)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
public class IdWorker
{
    //機器ID
    private static long workerId;
    private static long twepoch = 687888001020L; //唯一時間,這是一個避免重復(fù)的隨機量,自行設(shè)定不要大于當(dāng)前時間戳
    private static long sequence = 0L;
    private static int workerIdBits = 4; //機器碼字節(jié)數(shù)。4個字節(jié)用來保存機器碼(定義為Long類型會出現(xiàn),最大偏移64位,所以左移64位沒有意義)
    public static long maxWorkerId = -1L ^ -1L << workerIdBits; //最大機器ID
    private static int sequenceBits = 10; //計數(shù)器字節(jié)數(shù),10個字節(jié)用來保存計數(shù)碼
    private static int workerIdShift = sequenceBits; //機器碼數(shù)據(jù)左移位數(shù),就是后面計數(shù)器占用的位數(shù)
    private static int timestampLeftShift = sequenceBits + workerIdBits; //時間戳左移動位數(shù)就是機器碼和計數(shù)器總字節(jié)數(shù)
    public static long sequenceMask = -1L ^ -1L << sequenceBits; //一微秒內(nèi)可以產(chǎn)生計數(shù),如果達到該值則等到下一微妙在進行生成
    private long lastTimestamp = -1L;
 
    /// <summary>
    /// 機器碼
    /// </summary>
    /// <param name="workerId"></param>
    public IdWorker(long workerId)
    {
        if (workerId > maxWorkerId || workerId < 0)
            throw new Exception(string.Format("worker Id can't be greater than {0} or less than 0 ", workerId));
        IdWorker.workerId = workerId;
    }
 
    public long nextId()
    {
        lock (this)
        {
            long timestamp = timeGen();
            if (this.lastTimestamp == timestamp)
            { //同一微妙中生成ID
                IdWorker.sequence = (IdWorker.sequence + 1) & IdWorker.sequenceMask; //用&運算計算該微秒內(nèi)產(chǎn)生的計數(shù)是否已經(jīng)到達上限
                if (IdWorker.sequence == 0)
                {
                    //一微妙內(nèi)產(chǎn)生的ID計數(shù)已達上限,等待下一微妙
                    timestamp = tillNextMillis(this.lastTimestamp);
                }
            }
            else
            { //不同微秒生成ID
                IdWorker.sequence = 0; //計數(shù)清0
            }
            if (timestamp < lastTimestamp)
            { //如果當(dāng)前時間戳比上一次生成ID時時間戳還小,拋出異常,因為不能保證現(xiàn)在生成的ID之前沒有生成過
                throw new Exception(string.Format("Clock moved backwards.  Refusing to generate id for {0} milliseconds",
                    this.lastTimestamp - timestamp));
            }
            this.lastTimestamp = timestamp; //把當(dāng)前時間戳保存為最后生成ID的時間戳
            long nextId = (timestamp - twepoch << timestampLeftShift) | IdWorker.workerId << IdWorker.workerIdShift | IdWorker.sequence;
            return nextId;
        }
    }
 
    /// <summary>
    /// 獲取下一微秒時間戳
    /// </summary>
    /// <param name="lastTimestamp"></param>
    /// <returns></returns>
    private long tillNextMillis(long lastTimestamp)
    {
        long timestamp = timeGen();
        while (timestamp <= lastTimestamp)
        {
            timestamp = timeGen();
        }
        return timestamp;
    }
 
    /// <summary>
    /// 生成當(dāng)前時間戳
    /// </summary>
    /// <returns></returns>
    private long timeGen()
    {
        return (long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds;
    }
}
 
/// <summary>
/// 生成雪花ID
/// </summary>
public static class SnowFlake
{
    private static long _workerId = 9;
    private static IdWorker _idWorker = null;
 
    public static string NewId()
    {
        if (_idWorker == null)
            _idWorker = new IdWorker(_workerId);
        return _idWorker.nextId().ToString();
    }
}

調(diào)用示例

    var id = SnowFlake.NewId();
    MessageBox.Show(id.ToString());

注意事項

需要注意的是雪花算法嚴重依賴時間,所以當(dāng)發(fā)生服務(wù)器時鐘回撥的問題是會導(dǎo)致可能產(chǎn)生重復(fù)的id。當(dāng)然實際基本不會發(fā)生這種情況,生產(chǎn)環(huán)境中很少會回調(diào)服務(wù)器系統(tǒng)時間,如果實在要回撥時間也可以通過調(diào)整步長參數(shù)來解決。

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

相關(guān)文章

  • C#中使用@聲明變量示例(逐字標識符)

    C#中使用@聲明變量示例(逐字標識符)

    這篇文章主要介紹了C#中使用@聲明變量示例(逐字標識符)在C#中,@符號不僅可以加在字符串常量之前,使字符串不作轉(zhuǎn)義之用,還可以加在變量名之前,使變量名與關(guān)鍵字不沖突,這種用法稱為“逐字標識符”,需要的朋友可以參考下
    2015-06-06
  • Unity實現(xiàn)物體跟隨鼠標移動

    Unity實現(xiàn)物體跟隨鼠標移動

    這篇文章主要為大家詳細介紹了Unity實現(xiàn)物體跟隨鼠標移動,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • C#與PLC通訊的實現(xiàn)代碼

    C#與PLC通訊的實現(xiàn)代碼

    這篇文章主要介紹了C#與PLC通訊的實現(xiàn)代碼,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • C#實現(xiàn)發(fā)送簡單HTTP請求的方法

    C#實現(xiàn)發(fā)送簡單HTTP請求的方法

    這篇文章主要介紹了C#實現(xiàn)發(fā)送簡單HTTP請求的方法,涉及C#操作http的技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-04-04
  • 提取HTML代碼中文字的C#函數(shù)

    提取HTML代碼中文字的C#函數(shù)

    提取HTML代碼中文字的C#函數(shù)...
    2007-03-03
  • WPF實現(xiàn)繪制餅狀統(tǒng)計圖的示例代碼

    WPF實現(xiàn)繪制餅狀統(tǒng)計圖的示例代碼

    這篇文章主要為大家詳細介紹了如何使用WPF實現(xiàn)繪制簡單的餅狀統(tǒng)計圖,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-10-10
  • C#實現(xiàn)主窗體最小化后出現(xiàn)懸浮框及雙擊懸浮框恢復(fù)原窗體的方法

    C#實現(xiàn)主窗體最小化后出現(xiàn)懸浮框及雙擊懸浮框恢復(fù)原窗體的方法

    這篇文章主要介紹了C#實現(xiàn)主窗體最小化后出現(xiàn)懸浮框及雙擊懸浮框恢復(fù)原窗體的方法,涉及C#窗體及鼠標事件響應(yīng)的相關(guān)技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-08-08
  • 利用Aspose.Cells和Excel模板導(dǎo)出統(tǒng)計數(shù)據(jù)

    利用Aspose.Cells和Excel模板導(dǎo)出統(tǒng)計數(shù)據(jù)

    這篇文章主要為大家詳細介紹了利用Aspose.Cells和Excel模板導(dǎo)出復(fù)雜的統(tǒng)計數(shù)據(jù),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-12-12
  • c#生成自定義圖片方法代碼實例

    c#生成自定義圖片方法代碼實例

    在本篇文章中我們給大家分享了關(guān)于c#生成自定義圖片方法的相關(guān)內(nèi)容,有需要的朋友們可以參考下。
    2018-10-10
  • C#實現(xiàn)字符串首字母大寫的方法示例

    C#實現(xiàn)字符串首字母大寫的方法示例

    這篇文章主要給大家介紹了關(guān)于利用C#實現(xiàn)字符串首字母大寫的相關(guān)資料,這是在最近工作中遇到的一個需求,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-01-01

最新評論