C# Guid长度雪花(snowflake)简单生成器
标准的long雪花长度为64bit,还要浪费1bit,然后41位时间,10位workid,12位序列guid长度128位,64位完整的时间tick,32位workid,32位序列,可谓随便用满非常豪华也就是系统里可以根据需要有的地方存随机guid,有的地方存雪花guid,随便换随后还有提取时间的方法,由于是64位完整时间,直接拿出来转时间就好了这个类参考别人的代码,如果需要设计更完善的guid雪花
标准的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更长,可以分段放不同的内容
using System;
using System.Threading;
namespace Ruifei.Common
{
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()
{
return Next(DateTime.UtcNow);
}
/// <summary>
/// 仅用于历史数据批量生成Id,必须按时间顺序传入
/// </summary>
public Guid Next(DateTime dataTime)
{
var ticks = dataTime.ToUniversalTime().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);
}
public static DateTime GetLocalTime(Guid guid)
{
return GetTime(guid);
}
}
}
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)