您好,登錄后才能下訂單哦!
最近看了twitter的分布式自增ID算法Snowflak,自己根據(jù)開源的代碼寫了一個C#的版本,以記錄學(xué)習(xí)。 twitter的開源項目地址為:https://github.com/twitter/snowflake 用Scala實現(xiàn)
class IdWorker { //機器標識位數(shù) private const int WORKER_ID_BITS = 4; //機器標識位的最大值 private const long MAX_WORKER_ID = -1L ^ -1L << WORKER_ID_BITS; //毫秒內(nèi)自增位 private const int SEQUENCE_BITS = 10; //自增位最大值 private const long SEQUENCE_Mask = -1L ^ -1L << SEQUENCE_BITS; private const long twepoch = 1398049504651L; //時間毫秒值向左偏移位 private const int timestampLeftShift = SEQUENCE_BITS + WORKER_ID_BITS; //機器標識位向左偏移位 private const int WORKER_ID_SHIFT = SEQUENCE_BITS; private static readonly DateTime START_TIME = new System.DateTime(1970, 1, 1, 0, 0, 0, 0); private static readonly object LOCK = new object(); private long sequence = 0L; private long lastTimestamp = -1L; private long workerId; public IdWorker(long workerId) { if (workerId > MAX_WORKER_ID || workerId < 0) { throw new ArgumentException(string.Format("worker id can't be greater than {0} or less than 0", MAX_WORKER_ID)); } this.workerId = workerId; } /// <summary> /// 獲取下一個id值 /// </summary> /// <returns></returns> public long NextId() { lock (LOCK) { long timestamp = TimeGen(); //當(dāng)前時間小于上一次時間,錯誤 if (timestamp < this.lastTimestamp) { throw new Exception(string.Format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp)); } //當(dāng)前毫秒內(nèi) if (this.lastTimestamp == timestamp) { //+1 求余 this.sequence = (this.sequence + 1) & SEQUENCE_Mask; //當(dāng)前毫秒內(nèi)計數(shù)滿了,等待下一秒 if (this.sequence == 0) { timestamp = tilNextMillis(lastTimestamp); } } else //不是當(dāng)前毫秒內(nèi) { this.sequence = 0; //重置當(dāng)前毫秒計數(shù) } this.lastTimestamp = timestamp; //當(dāng)前毫秒值 | 機器標識值 | 當(dāng)前毫秒內(nèi)自增值 long nextId = ((timestamp - twepoch << timestampLeftShift)) | (this.workerId << WORKER_ID_SHIFT) | (this.sequence); return nextId; } } /// <summary> /// 等待下一個毫秒 /// </summary> /// <param name="lastTimestamp"></param> /// <returns></returns> private long tilNextMillis(long lastTimestamp) { long timestamp = TimeGen(); while (timestamp <= lastTimestamp) { timestamp = TimeGen(); } return timestamp; } /// <summary> /// 獲取當(dāng)前時間的Unix時間戳 /// </summary> /// <returns></returns> private long TimeGen() { return (DateTime.UtcNow.Ticks - START_TIME.Ticks) / 10000; } }
調(diào)用方式如下
static void Main(string[] args) { IdWorker worker = new IdWorker(12L); for (int i = 0; i < 100000; i++) { Console.WriteLine(worker.NextId()); } }
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。