C# Guid長度雪花(snowflake)簡單生成器


標准的long雪花長度為64bit,還要浪費1bit,然后41位時間,10位workid,12位序列

guid長度128位,64位完整的時間tick,32位workid,32位序列,可謂隨便用滿非常豪華

也就是系統里可以根據需要有的地方存隨機guid,有的地方存雪花guid,隨便換

隨后還有提取時間的方法,由於是64位完整時間,直接拿出來轉時間就好了

 

這個類參考別人的代碼,如果需要設計更完善的guid雪花,可以在github上或者nuget上找newid這個項目,老外寫好的更完善的做法

 

guid長度雪花繼承雪花id所有優點和特點,只是長度略長

可以用guid存儲,以往習慣guid的人沒有壓力,對guid支持較好的數據庫就能支持好guid雪花,mysql不行

一個項目不同表可以使用不同策略,有的用guid,有的用雪花guid,按需使用,也更方便導數據

時間儲存的完整long,可以提取出完整時間,時間照樣從0年開始,再老的數據也可以導,只要按時間順序,自己傳個時間給next方法

序列號數量充足,不會動不動就加1秒,workid更長,可以分段放不同的內容

 

 

 

public class GuidSnowFlakeGenerator
    {
        readonly uint _c;
        int _a;
        int _b;
        long _lastTick;
        uint _sequence;

        SpinLock _spinLock;

        public GuidSnowFlakeGenerator(uint workId)
        {
            _spinLock = new SpinLock(false);
            _c = workId;
        }

        public Guid Next()
        {
            var ticks = DateTime.UtcNow.Ticks;

            int a;
            int b;
            uint sequence;

            var lockTaken = false;
            try
            {
                _spinLock.Enter(ref lockTaken);

                if (ticks > _lastTick)
                    UpdateTimestamp(ticks);
                else if (_sequence == uint.MaxValue)
                    UpdateTimestamp(_lastTick + 1);

                sequence = _sequence++;

                a = _a;
                b = _b;
            }
            finally
            {
                if (lockTaken)
                    _spinLock.Exit();
            }

            var s = sequence;
            byte[] bytes = new byte[16];
            bytes[0] = (byte)(a >> 24);
            bytes[1] = (byte)(a >> 16);
            bytes[2] = (byte)(a >> 8);
            bytes[3] = (byte)a;
            bytes[4] = (byte)(b >> 24);
            bytes[5] = (byte)(b >> 16);
            bytes[6] = (byte)(b >> 8);
            bytes[7] = (byte)b;
            bytes[8] = (byte)(_c >> 24);
            bytes[9] = (byte)(_c >> 16);
            bytes[10] = (byte)(_c >> 8);
            bytes[11] = (byte)(_c);
            bytes[12] = (byte)(s >> 24);
            bytes[13] = (byte)(s >> 16);
            bytes[14] = (byte)(s >> 8);
            bytes[15] = (byte)(s >> 0);

            return new Guid(bytes);
        }


        void UpdateTimestamp(long tick)
        {
            _b = (int)(tick & 0xFFFFFFFF);
            _a = (int)(tick >> 32);

            _sequence = 0;
            _lastTick = tick;
        }

        public static DateTime GetTime(Guid guid)
        {
            var bytes = guid.ToByteArray();
            long tick = (long)bytes[0] << 56;
            tick += (long)bytes[1] << 48;
            tick += (long)bytes[2] << 40;
            tick += (long)bytes[3] << 32;
            tick += (long)bytes[3] << 24;
            tick += (long)bytes[3] << 16;
            tick += (long)bytes[3] << 8;
            tick += (long)bytes[3];
            return new DateTime(tick, DateTimeKind.Utc);
        }
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM