Einleitung
Dies ist auf der Grundlage der Twitter-Schneeflocke geschrieben. Hier ist die chinesische Einführung.
Wie gezeigt In der Abbildung oben sind für eine 64-Bit-ID mit Ausnahme des Vorzeichenbits ganz links (festgelegt auf 0, um sicherzustellen, dass alle generierten IDs positive Zahlen sind) noch 63 Bits verfügbar.
Der folgende Code ist Das gleiche wie in der Abbildung. Mit Ausnahme der 10-Bit-Arbeitsmaschinen-ID in der Mitte kann die Anzahl der Ziffern im Zeitstempel und in der Seriennummer entsprechend Ihren eigenen Anforderungen geändert werden. Sie können die Arbeitsmaschinen-ID in der Mitte nach links oder nach rechts verschieben.
Code
/// <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('1', 53 - indexBitLength), 2); indexMax = Convert.ToInt64(new string('1', 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; } } }
Codebeschreibung
Wenn Sie es verwenden, Sie müssen eine neue Instanz von IdCreator erstellen und dann die Methode Create() aufrufen. Sie müssen die Instanz von IdCreator einer statischen Variablen zuweisen, um die Eindeutigkeit der ID-Nummer sicherzustellen Bei der Bereitstellung müssen Sie den Parameter „instanceID“ an den Konstruktor von „IdCreator“ übergeben. Jede Bereitstellung muss einen anderen Wert im Bereich von 0 bis 1023 haben. Der Parameter „indexBitLength“ im Konstruktor
stellt die Länge der Seriennummer ganz rechts dar ' in der Abbildung. Es ist nicht mehr auf 12 Bit festgelegt und reicht von 1 bis 32 Bit, wobei der Zeitstempel übrig bleibt.
Hinweis: Der Zeitstempel der IdCreator-Klasse wird in Sekunden gemessen Wenn Sie es in Millisekunden ändern möchten, müssen Sie nur den Code long ts = Harry.Common.Utils.GetTimeStamp() / 1000; in long ts = Harry.Common.Utils.GetTimeStamp(); ändern.
Beispielcode
IdCreator c=new IdCreator(0,16); var id=c.Create();