zoukankan      html  css  js  c++  java
  • 基于.NET Standard的分布式自增ID算法--Snowflake代码实现

    概述

    上篇文章介绍了3种常见的Id生成算法,本篇主要介绍如何使用C#实现Snowflake。

    基础字段

    /// <summary>
    /// 工作节点Id(长度为5位)
    /// </summary>
    public long WorkId{get;protected set;}
    
    /// <summary>
    /// 机房Id(长度为5位)
    /// </summary>
    public long DataCenterId{get;protected set;}
    
    /// <summary>
    /// 当前生成的Id
    /// </summary>
    public long CurrentId { get;protected set; }
    
    

    基础方法

    //获取当前时间的Unix时间戳
     private long TimeGen()
    {
          return DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
    }
    
    //生成新时间戳(一定比上次生成的时间戳大)
     private long TilNextMillis(long lastTimestamp)
     {
          var timestamp = TimeGen();
          while (timestamp <= lastTimestamp)
          {
               timestamp = TimeGen();
          }
           return timestamp;
    }
    
    

    Id生成核心方法

            private const long TwEpoch = 1543765593681L;//2018-12-2 15:47:06 +00:00
    
            private const int WorkerIdBits = 5;
            private const int DatacenterIdBits = 5;
            private const int SequenceBits = 12;
            private const long MaxWorkerId = -1L ^ (-1L << WorkerIdBits);
            private const long MaxDatacenterId = -1L ^ (-1L << DatacenterIdBits);
    
            private const int WorkerIdShift = SequenceBits;
            private const int DatacenterIdShift = SequenceBits + WorkerIdBits;
            private const int TimestampLeftShift = SequenceBits + WorkerIdBits + DatacenterIdBits;
            private const long SequenceMask = -1L ^ (-1L << SequenceBits);
    
            private long _sequence = 0L;
            private long _lastTimestamp = -1L;
    
            private readonly object _lock = new object();
            
             public long NextId()
            {
                lock (_lock)
                {
                    var timestamp = TimeGen();
                    if (timestamp < _lastTimestamp)
                    {
                        //TODO 是否可以考虑直接等待?
                        throw new Exception(
                            $"Clock moved backwards or wrapped around. Refusing to generate id for {_lastTimestamp - timestamp} ticks");
                    }
    
                    if (_lastTimestamp == timestamp)
                    {
                        _sequence = (_sequence + 1) & SequenceMask;
                        if (_sequence == 0)
                        {
                            timestamp = TilNextMillis(_lastTimestamp);
                        }
                    }
                    else
                    {
                        _sequence = 0;
                    }
                    _lastTimestamp = timestamp;
                    CurrentId = ((timestamp - TwEpoch) << TimestampLeftShift) |
                             (DatacenterId << DatacenterIdShift) |
                             (WorkerId << WorkerIdShift) | _sequence;
    
                    return CurrentId;
                }
            }
    
    完整实现、使用Demo以及benchmark测试请参见源代码:https://github.com/sampsonye/nice
    
    
    
  • 相关阅读:
    hdu 1269 迷宫城堡(强联通分量,基础)
    hdu 2102 A计划(BFS,基础)
    python 变量命名规范
    rpm常用选项
    memcached
    session共享
    Nginx高级使用
    nginx 反向代理
    Nginx基本使用
    github 建立博客
  • 原文地址:https://www.cnblogs.com/leafly/p/10089540.html
Copyright © 2011-2022 走看看