前言
雪花ID是用一个64位的整形数字来做ID,对应.net中的long,数据库中的bigint,雪花算法的原始版本是scala版,用于生成分布式主键ID(纯数字,时间顺序),订单编号等。
自增ID:对于数据敏感场景不宜使用,且不适合于分布式场景。
GUID:采用无意义字符串,数据量增大时造成访问过慢,且不宜排序。
生成GUID
var UUID = Guid.NewGuid().ToString("N").ToUpper();
生成雪花ID
var ids = new IDCreater();
ids.NextID();
雪花ID类代码
public class IDCreater
{
private const long Send = 1576492637564;//初始种子
//时间戳41位+序列10位+机器码10位+随机3位
private static int IndexBits = 10;//序列位
private static int WorkerBits = 10;//机器位
private static int RandomBits = 3;//随机位
private static long Index = 0;
private static long Worker = 0;
private static long IndexMax = -1 ^ (-1 << IndexBits);
public static long WorkerMax = -1 ^ (-1 << WorkerBits);
private static long RandomMax = -1 ^ (-1 << RandomBits);
// 机器码偏左移13位
private static int WorkerShift = RandomBits;
// 序列位偏左移3位
private static int IndexShift = WorkerBits + RandomBits;
// 时间毫秒左移23位
private static int TimeStampShift = IndexBits + WorkerBits + RandomBits;
private static Random r = new Random(Guid.NewGuid().GetHashCode());
private static long LastTimeStamp = 0;
/ <summary>
/ 初始化自行分配机器码
/ </summary>
//public IDCreater(long Worker = 0)
//{
// if (Worker > WorkerMax || Worker < 0)
// throw new Exception(string.Format("机器位只能是 0 至 {0}之间", WorkerMax));
// IDCreater.Worker = Worker;
//}
/// <summary>
/// 生成一个ID
/// </summary>
/// <returns></returns>
public long NextID()
{
lock (this)
{
long ts = GetTimeStamp();
if (ts == LastTimeStamp)
{
Index = (Index + 1) & IndexMax;
if (Index == 0) ts = NextTimeStamp();
}
else
{
Index = 0;
}
if (ts < LastTimeStamp)
{
Thread.Sleep((int)(LastTimeStamp - ts));
//throw new Exception("NTP 回拨时间");
}
LastTimeStamp = ts;
//long random = r.Next(0, (int)RandomMax);
return ((ts - Send) << TimeStampShift) | (Index << IndexShift) | (Worker << WorkerShift);
}
}
/// <summary>
/// 阻塞到下一个毫秒,直到获得新的时间
/// </summary>
/// <returns></returns>
private long NextTimeStamp()
{
long ts = GetTimeStamp();
while (ts <= LastTimeStamp)
{
ts = GetTimeStamp();
}
return ts;
}
private static DateTime UTC0 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
/// <summary>
/// 获取当前时间
/// </summary>
/// <returns></returns>
private static long GetTimeStamp()
{
return (long)(DateTime.UtcNow - UTC0).TotalMilliseconds;
}
}