using Masuit.Tools.DateTimeExt; using Masuit.Tools.Strings; using System; namespace Masuit.Tools.Systems { /// /// 动态生产有规律的分布式ID /// public class SnowFlake { #region 私有字段 private static long _machineId; //机器码 private static long _datacenterId; //数据ID private static long _sequence; //计数从零开始 private static long _lastTimestamp = -1L; //最后时间戳 private const long Twepoch = 687888001020L; //唯一时间随机量 private const long MachineIdBits = 5L; //机器码字节数 private const long DatacenterIdBits = 5L; //数据字节数 private const long MaxMachineId = -1L ^ -1L << (int)MachineIdBits; //最大机器码 private const long MaxDatacenterId = -1L ^ (-1L << (int)DatacenterIdBits); //最大数据ID private const long SequenceBits = 12L; //计数器字节数,12个字节用来保存计数码 private const long MachineIdShift = SequenceBits; //机器码数据左移位数,就是后面计数器占用的位数 private const long DatacenterIdShift = SequenceBits + MachineIdBits; private const long TimestampLeftShift = DatacenterIdShift + DatacenterIdBits; //时间戳左移动位数就是机器码+计数器总字节数+数据字节数 private const long SequenceMask = -1L ^ -1L << (int)SequenceBits; //一毫秒内可以产生计数,如果达到该值则等到下一毫秒在进行生成 private static readonly object SyncRoot = new object(); //加锁对象 private static readonly NumberFormater NumberFormater = new NumberFormater(36); private static SnowFlake _snowFlake; #endregion /// /// 创建一个实例 /// /// public static SnowFlake GetInstance() { return _snowFlake ?? (_snowFlake = new SnowFlake()); } /// /// 默认构造函数 /// public SnowFlake() { Snowflakes(0, -1); } /// /// 构造函数 /// /// 机器码 public SnowFlake(long machineId) { Snowflakes(machineId, -1); } /// /// 构造函数 /// /// 机器码 /// 数据中心id public SnowFlake(long machineId, long datacenterId) { Snowflakes(machineId, datacenterId); } private void Snowflakes(long machineId, long datacenterId) { if (machineId >= 0) { if (machineId > MaxMachineId) { throw new Exception("机器码ID非法"); } _machineId = machineId; } if (datacenterId >= 0) { if (datacenterId > MaxDatacenterId) { throw new Exception("数据中心ID非法"); } _datacenterId = datacenterId; } } /// /// 获取长整形的ID /// /// public long GetLongId() { lock (SyncRoot) { var timestamp = (long)DateTime.UtcNow.GetTotalMilliseconds(); if (_lastTimestamp == timestamp) { //同一毫秒中生成ID _sequence = (_sequence + 1) & SequenceMask; //用&运算计算该毫秒内产生的计数是否已经到达上限 if (_sequence == 0) { //一毫秒内产生的ID计数已达上限,等待下一毫秒 timestamp = (long)DateTime.UtcNow.GetTotalMilliseconds(); } } else { //不同毫秒生成ID _sequence = 0L; } _lastTimestamp = timestamp; //把当前时间戳保存为最后生成ID的时间戳 long id = ((timestamp - Twepoch) << (int)TimestampLeftShift) | (_datacenterId << (int)DatacenterIdShift) | (_machineId << (int)MachineIdShift) | _sequence; return id; } } /// /// 获取一个字符串表示形式的id /// /// public string GetUniqueId() { return NumberFormater.ToString(GetLongId()); } /// /// 获取一个字符串表示形式的id /// /// 最大长度,至少6位 /// public string GetUniqueShortId(int maxLength = 8) { if (maxLength < 6) { throw new ArgumentException("最大长度至少需要6位"); } string id = GetUniqueId(); int index = id.Length - maxLength; if (index < 0) { index = 0; } return id.Substring(index); } } }