C# Guid长度雪花(snowflake)简单生成器
标准的long雪花长度为64bit,还要浪费1bit,然后41位时间,10位workid,12位序列
guid长度128位,64位完整的时间tick,32位workid,32位序列,可谓随便用满非常豪华
也就是系统里可以根据需要有的地方存随机guid,有的地方存雪花guid,随便换
随后还有提取时间的方法,由于是64位完整时间,直接拿出来转时间就好了
这个类参考别人的代码,如果需要设计更完善的guid雪花,可以在github上或者nuget上找newid这个项目,老外写好的更完善的做法
guid长度雪花继承雪花id所有优点和特点,只是长度略长
可以用guid存储,以往习惯guid的人没有压力,对guid支持较好的数据库就能支持好guid雪花,mysql不行
一个项目不同表可以使用不同策略,有的用guid,有的用雪花guid,按需使用,也更方便导数据
时间储存的完整long,可以提取出完整时间,时间照样从0年开始,再老的数据也可以导,只要按时间顺序,自己传个时间给next方法
序列号数量充足,不会动不动就加1秒,workid更长,可以分段放不同的内容
public class GuidSnowFlakeGenerator { readonly uint _c; int _a; int _b; long _lastTick; uint _sequence; SpinLock _spinLock; public GuidSnowFlakeGenerator(uint workId) { _spinLock = new SpinLock(false); _c = workId; } public Guid Next() { var ticks = DateTime.UtcNow.Ticks; int a; int b; uint sequence; var lockTaken = false; try { _spinLock.Enter(ref lockTaken); if (ticks > _lastTick) UpdateTimestamp(ticks); else if (_sequence == uint.MaxValue) UpdateTimestamp(_lastTick + 1); sequence = _sequence++; a = _a; b = _b; } finally { if (lockTaken) _spinLock.Exit(); } var s = sequence; byte[] bytes = new byte[16]; bytes[0] = (byte)(a >> 24); bytes[1] = (byte)(a >> 16); bytes[2] = (byte)(a >> 8); bytes[3] = (byte)a; bytes[4] = (byte)(b >> 24); bytes[5] = (byte)(b >> 16); bytes[6] = (byte)(b >> 8); bytes[7] = (byte)b; bytes[8] = (byte)(_c >> 24); bytes[9] = (byte)(_c >> 16); bytes[10] = (byte)(_c >> 8); bytes[11] = (byte)(_c); bytes[12] = (byte)(s >> 24); bytes[13] = (byte)(s >> 16); bytes[14] = (byte)(s >> 8); bytes[15] = (byte)(s >> 0); return new Guid(bytes); } void UpdateTimestamp(long tick) { _b = (int)(tick & 0xFFFFFFFF); _a = (int)(tick >> 32); _sequence = 0; _lastTick = tick; } public static DateTime GetTime(Guid guid) { var bytes = guid.ToByteArray(); long tick = (long)bytes[0] << 56; tick += (long)bytes[1] << 48; tick += (long)bytes[2] << 40; tick += (long)bytes[3] << 32; tick += (long)bytes[3] << 24; tick += (long)bytes[3] << 16; tick += (long)bytes[3] << 8; tick += (long)bytes[3]; return new DateTime(tick, DateTimeKind.Utc); } }