>  기사  >  类库下载  >  C# 분산 ID 생성기

C# 분산 ID 생성기

高洛峰
高洛峰원래의
2016-11-04 16:48:472001검색

소개

트위터의 눈꽃송이를 바탕으로 쓴 글입니다.

C# 분산 ID 생성기


보시다시피 위 그림에서 64비트 ID는 가장 왼쪽 부호 비트(생성된 ID가 모두 양수인지 확인하기 위해 0으로 고정)를 제외하고 나머지 63비트를 사용할 수 있습니다.

아래 코드는 다음과 같습니다. 그림과 동일합니다. 가운데의 10비트 작업 기계 ID를 제외하고는 타임스탬프의 자릿수와 일련번호가 사용자의 필요에 따라 변경될 수 있습니다. 중앙에 있는 작업기 ID를 왼쪽으로 이동시키거나, 오른쪽으로 이동하시면 됩니다.

코드

/// <summary>
    /// 64位ID生成器,最高位为符号位,始终为0,可用位数63.
    /// 实例编号占10位,范围为0-1023
    /// 时间戳和索引共占53位
    /// </summary>
    public sealed class IdCreator
    {        long timestamp = 0;//当前时间戳
        long index = 0;//索引/计数器
        long instanceID;//实例编号
        int indexBitLength;//索引可用位数
        long tsMax = 0;//时间戳最大值
        long indexMax = 0;        static IdCreator _default = new IdCreator();        /// <summary>
        /// 
        /// </summary>
        /// <param name="instanceID">实例编号(0-1023)</param>
        /// <param name="indexBitLength">索引可用位数(1-32).每秒可生成ID数等于2的indexBitLength次方.大并发情况下,当前秒内ID数达到最大值时,将使用下一秒的时间戳,不影响获取ID.</param>
        /// <param name="initTimestamp">初始化时间戳,精确到秒.当之前同一实例生成ID的timestamp值大于当前时间的时间戳时,
        /// 有可能会产生重复ID(如持续一段时间的大并发请求).设置initTimestamp比最后的时间戳大一些,可避免这种问题</param>
        public IdCreator(int instanceID, int indexBitLength, long? initTimestamp = null)        {            if (instanceID < 0)
            {                //这里给每个实例随机生成个实例编号
                Random r = new Random();                this.instanceID = r.Next(0, 1024);
            }            else
            {                this.instanceID = instanceID % 1024;
            }            if (indexBitLength < 1)
            {                this.indexBitLength = 1;
            }            else if (indexBitLength > 32)            {                this.indexBitLength = 32;
            }            else
            {                this.indexBitLength = indexBitLength;
            }
            tsMax = Convert.ToInt64(new string(&#39;1&#39;, 53 - indexBitLength), 2);
            indexMax = Convert.ToInt64(new string(&#39;1&#39;, indexBitLength), 2);            if (initTimestamp != null)
            {                this.timestamp = initTimestamp.Value;
            }
        }        /// <summary>
        /// 默认每实例每秒生成65536个ID,从1970年1月1日起,累计可使用4358年
        /// </summary>
        /// <param name="instanceID">实例编号(0-1023)</param>
        public IdCreator(int instanceID) : this(instanceID, 16)        {

        }        /// <summary>
        /// 默认每秒生成65536个ID,从1970年1月1日起,累计可使用4358年
        /// </summary>
        public IdCreator() : this(-1)        {

        }        /// <summary>
        /// 生成64位ID
        /// </summary>
        /// <returns></returns>
        public long Create()        {            long id = 0;            lock (this)
            {                //增加时间戳部分
                long ts = Harry.Common.Utils.GetTimeStamp() / 1000;

                ts = ts % tsMax;  //如果超过时间戳允许的最大值,从0开始
                id = ts << (10 + indexBitLength);//腾出后面部分,给实例编号和缩引编号使用

                //增加实例部分
                id = id | (instanceID << indexBitLength);                //获取计数
                if (timestamp < ts)
                {
                    timestamp = ts;
                    index = 0;
                }                else
                {                    if (index > indexMax)
                    {
                        timestamp++;
                        index = 0;
                    }
                }

                id = id | index;

                index++;
            }            return id;
        }        /// <summary>
        /// 获取当前实例的时间戳
        /// </summary>
        public long CurrentTimestamp
        {            get
            {                return this.timestamp;
            }
        }        /// <summary>
        /// 默认每实例每秒生成65536个ID,从1970年1月1日起,累计可使用4358年
        /// </summary>
        public static IdCreator Default
        {            get
            {                return _default;
            }
        }
    }

코드 설명

사용시 IdCreator의 새 인스턴스를 생성한 다음 Create() 메서드를 호출해야 합니다. ID 번호를 생성하려면 ID 번호의 고유성을 보장하기 위해 IdCreator의 인스턴스를 할당해야 합니다. 배포의 경우, IdCreator의 생성자에 인스턴스ID 매개변수를 전달해야 합니다. 각 배포에는 0-1023 범위의 다른 값이 있어야 합니다.

생성자의 indexBitLength 매개변수는 가장 오른쪽 '일련번호'의 길이를 나타냅니다. '는 더 이상 12비트로 고정되지 않으며 범위는 1-32입니다. 나머지는 사용 가능한 비트이므로 타임스탬프는 그대로 유지됩니다.

참고: IdCreator 클래스의 타임스탬프는 초 단위로 측정됩니다. 밀리초로 변경하려면 코드만 변경하면 됩니다. long ts = Harry.Common.Utils.GetTimeStamp() / 1000; long ts = Harry.Common.Utils.GetTimeStamp();.

샘플 코드

 IdCreator c=new IdCreator(0,16); 
  var id=c.Create();


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.