SnowflakeID csharp 版本

介绍了一种基于Twitter Snowflake算法的分布式ID生成器的C#实现,该生成器能够生成全局唯一且递增的ID,适用于分布式系统,以替代数据库自增和GUID,具有良好的性能和有序性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

分布式 SnowflakeID 方案,这是自己改的 CSharp 版本的,已在各个项目中广泛使用。 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace App.Utils
{
    /// <summary>
    /// Twitter SnowflakeID 分布式 ID 生成器。
    /// 用于分布式系统中生成全局唯一且递增的Id,可用于取代数据库自增(易被试探)及GUID(性能很差)。
    /// </summary>
    /// <remarks>
    /// 共64位(用 long 容纳),默认分配如下:
    ///   第1部分:01位,始终为0, 表示正数
    ///   第2部分:41位,精确为毫秒的时间戳, 可以使用 2^41 毫秒 = 69.73 年
    ///   第3部分:10位,机器码(0-1023)
    ///   第4部分:12位,序列号(0-4095)
    /// 优点: 
    ///   按ID递增,易于在数据库中插入和检索,比GUID要好(128位且无序)
    ///   不依赖数据库,在内存中生成,性能好
    /// 备注:
    ///   实际使用时要创建单例对象,减少创建开销,加快生成速度。
    ///   经实际测试,毫秒内的序列号可以生成完整(0-4095)
    ///   一般一个系统也不会使用70年,基本够用了。
    ///   实在不够用了怎么办? 时间戳再分配几位,如43位 => 2^43毫秒 = 278.92 年
    /// 参考:
    ///   https://blog.youkuaiyun.com/weixin_40990818/article/details/82745567
    /// </remarks>
    /// <example>
    /// var snow = new SnowflakeID(1, 2010);
    /// var id = snow.NewID();
    /// </example>
    public class SnowflakeID
    {
        // 属性
        public int  StartYear { get; set; }     // 开始年份
        public long TimeStamp { get; set; }     // 时间戳毫秒
        public long Machine { get; set; }       // 设备编号
        public long Sequence { get; set; }      // 毫秒内序列

        // 位数
        public int TimeStampBits = 41;           // 时间戳位数
        public int MachineBits = 10;             // 机器编号位数
        public int SequenceBits = 12;            // 序列位数

        // 掩码
        private long _timestampMask;
        private long _machineMask;
        private long _sequenceMask;

        // 静态变量
        static readonly object _lock = new object();     // 互斥锁
        static long _lastTimeStamp = -1L;        // 上次时间截
        static long _lastSequence = 0;           // 上次序列号

        /// <summary>长整形值</summary>
        public long Value
        {
            get
            {
                // 移位并通过或运算拼到一起组成64位的ID
                long span = this.TimeStamp - new DateTime(this.StartYear, 1, 1).Ticks / 10000;
                return  (span << (MachineBits + SequenceBits))
                      | (this.Machine << SequenceBits)
                      | this.Sequence
                      ;
            }
            private set
            {
                // 解析
                this.TimeStamp = (value >> (MachineBits + SequenceBits)) & _timestampMask;
                this.Machine   = (value >> SequenceBits) & _machineMask;
                this.Sequence  = value & _sequenceMask;
            }
        }

        /// <summary>解析ID结构</summary>
        public static SnowflakeID Parse(long id)
        {
            SnowflakeID snow = new SnowflakeID();
            snow.Value = id;
            return snow;
        }

        /// <summary>构造函数</summary>
        /// <param name="machine">机器编码(0-1023)</param>
        public SnowflakeID(int machine=1, int startYear=2010, int timeStampBits=41, int machineBits=10, int sequenceBits=12)
        {
            if (machine > 1023 || machine < 0)
                throw new Exception("machine must less then 1024");
            this.Machine = machine;
            this.StartYear = startYear;
            this.TimeStampBits = timeStampBits;
            this.MachineBits = machineBits;
            this.SequenceBits = sequenceBits;
            // 掩码
            this._timestampMask = (1L << TimeStampBits) - 1;
            this._machineMask   = (1L << MachineBits) - 1;
            this._sequenceMask  = (1L << SequenceBits) - 1;
        }


        /*
        /// <summary>生成</summary>
        public static long NewID(int machine = 1, int startYear = 2010, int timeStampBits = 41, int machineBits = 10, int sequenceBits = 12)
        {
            return new SnowflakeID(machine, startYear, timeStampBits, machineBits, sequenceBits)
                .New().Value;
        }
        */

        /// <summary>生成</summary>
        public long NewID()
        {
            return New().Value;
        }

        /// <summary>生成</summary>
        protected SnowflakeID New()
        {
            lock (_lock)
            {
                var timestamp = GetTimeStamp();
                if (timestamp != _lastTimeStamp)
                    _lastSequence = 0;
                else
                {
                    // 如果是同一毫秒生成的,则进行毫秒内序列(默认12位,值范围为0-4095, 2^12-1)
                    // 如果毫秒内序列溢出, 阻塞到下一个毫秒,获得新的时间戳
                    _lastSequence = (_lastSequence + 1) & _sequenceMask;
                    if (_lastSequence == 0)
                        timestamp = WaitNextMS(_lastTimeStamp);
                }
                _lastTimeStamp = timestamp;

                //
                this.TimeStamp = timestamp;
                this.Sequence = _lastSequence;
                return this;
            }
        }


        // 阻塞到下一个毫秒,直到获得新的时间戳
        static long WaitNextMS(long lastTimestamp)
        {
            long timestamp = GetTimeStamp();
            while (timestamp <= lastTimestamp)
                timestamp = GetTimeStamp();
            return timestamp;
        }

        //  获取时间戳(毫秒)
        static long GetTimeStamp()
        {
            return DateTime.Now.Ticks / 10000;
        }

        /// <summary>SnowflakeID 生成器单例</summary>
        public static SnowflakeID Instance
        {
            get
            {
                return IO.GetCache<SnowflakeID>("__SnowFlaker", () => {
                    var machineId = UtilConfig.Instance.MachineId;
                    return new SnowflakeID(machineId, 2010, 41, 10, 12);
                });
            }
        }
    }
}

测试用例

        [TestMethod()]
        public void SnowflakeIDTest()
        {
            // 生成
            var snow = new SnowflakeID(1);
            var ids = new List<long>();
            for (int i = 0; i < 1000; i++)
            {
                long id = snow.NewID();
                ids.Add(id);
            }

            // 输出结果
            foreach (var id in ids)
            {
                IO.Write("{0} : {1}", id.ToString(), id.ToBitString());
            }

            // 解析
            var snowId = SnowflakeID.Parse(1259605479504482304);
            var timestamp = snowId.TimeStamp;
            var machine = snowId.Machine;
            var sequence = snowId.Sequence;
        }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

土豆湿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值