• SnowFlake全局唯一ID算法C#实现事例


    public class SnowFlake
        {
            /// <summary>
            /// 总机器位数
            /// </summary>
            private static readonly int WorkBits = 5;
            /// <summary>
            /// 自增序列号位数
            /// </summary>
            private static readonly int SequenceBits = 16;
            /// <summary>
            /// 序列号最大值 0开始 
            /// </summary>
            private static readonly long SequenceMax = 1L << SequenceBits;
            /// <summary>
            /// 服务器最大值
            /// </summary>
            private static readonly long WorkMax = 1L << WorkBits;
            /// <summary>
            /// 当前机器号 0-WorkMax
            /// </summary>
            private static long CurrentWorkId = 0;
            /// <summary>
            /// 加锁对象
            /// </summary>
            private readonly object objlock = new object();
            /// <summary>
            /// 记录上次时间戳
            /// </summary>
            private static long LastTime;
            /// <summary>
            /// 当前序列号 0开始
            /// </summary>
            private static long CurrentSequence = -1;
            public SnowFlake(int _CurrentWorkId)
            {
                CurrentWorkId = _CurrentWorkId;
                Console.WriteLine(SequenceMax);
            }
            /// <summary>
            /// 自定义时间戳
            /// </summary>
            /// <returns></returns>
            private long GetTime()
            {
                return (long)(DateTime.UtcNow - new DateTime(2020, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;
            }
    
    
            /// <summary>
            /// 获取ID
            /// </summary>
            /// <returns></returns>
            public long NextId()
            {
                lock (objlock)
                {
                    if (CurrentWorkId >= WorkMax)
                    {
                        throw new Exception($"机器码不能大于最大机器码值{WorkMax}");
                    }
                    var time = GetTime();
                    //同秒内序列号自增
                    if (time == LastTime)
                    {
                        //序列号超出最大 等待下一个时间点
                        if (CurrentSequence >= SequenceMax)
                        {
                            //等待下一个时间点
                            while (time == LastTime)
                            {
                                time = GetTime();
                            }
                            CurrentSequence = -1;
                            LastTime = time;
                        }
                    }
                    else
                    {
                        //不同秒 重新自增
                        CurrentSequence = -1;
                        LastTime = time;
                    }
                    CurrentSequence++;
    
                    //Console.WriteLine(DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss fff"));
                    //Console.WriteLine(CurrentSequence);
    
                    var num = (WorkBits + SequenceBits);
                    return time << num | CurrentWorkId << SequenceBits | CurrentSequence;
                }
            }
    
           
        }

    以上代码为个人理解写法,若有不足,请指正。

    实际的算法为 1个0bit+41bit时间戳+10bit机器码+12bit序列号; 最终得到的是64bit的二进制 也就是能支持int64最大值,可支持单机器每秒400多W的ID生成;

    但js的最大Number类型是53bit,且常用系统也达不到这么多并发,所以参考了廖雪峰老师的意见 修改为

    32bit的秒级时间戳(现计算结果为31bit)+5bit的机器码+16bit的序列号 共53bit,而且时间戳未使用1970默认算法,采用了自定义年份,以上代码可支持最大2^5=32个机器 每台机器2^16=65535个ID生成。

    SnowFlake算法其他理解参考 https://www.cnblogs.com/firstdream/p/9055771.html

    查看int的bit可用 Convert.ToString(num, 2);查看

    << 左偏移 右边补齐0 

    | 或算法 

     

  • 相关阅读:
    。。。
    __new__ 单例
    bokeh
    空间数据可视化
    关系网络图
    Pandas 50题练习
    seaborn
    数据输出及内容美化 简单介绍
    数据分析---项目总结
    数学建模
  • 原文地址:https://www.cnblogs.com/DDSkay/p/13963225.html
Copyright © 2020-2023  润新知