平台提供接口
生成guid(值替换为雪花算法)
{ip}/bo/api/v3/db/help/guid
{ip}/bo/api/v3/db/help/snowflake/guid?id=
雪花ID,逆向解析
{ip}/bo/api/v3/db/help/snowflake/analyze/{id}
注入服务
private readonly IGuid _guidRepository;
IGuid guidRepository,
_guidRepository = guidRepository;
public string GetDataGuid
雪花算法 (DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc))
开源项目
https://github.com/stulzq/snowflake-net/tree/master/Demo
https://gitee.com/itsm/learning_example/tree/master/snowflake-%E9%9B%AA%E8%8A%B1Id
把guid生成规则改成雪花算法
/// <summary>
/// 获取 主键ID信息
/// </summary>
/// <param name="ownerId"></param>
/// <param name="sysId"></param>
/// <param name="dictionaryUrl"></param>
/// <param name="noGidSnowflake">是否禁用雪花算法获取ID</param>
/// <returns></returns>
public string GetDataGuid([RequiredStringPF("ownerId")] string ownerId, string sysId, Dictionary<string, object> dictionaryUrl, bool noGidSnowflake = false)
{
sysId = sysId ?? "sys";
string envId = EnvPFUtil.CurrentEnv();
string configKey = $"snowflake:machine:{envId}{ownerId}{sysId}";
long datacenterId = _configuration.GetValue<long>(configKey);
if (_configuration.GetValue<bool>("snowflake:machine:no"))
{
string guid = Guid.NewGuid().ToString();
StringBuilder sbGuid = new StringBuilder();
if (!string.IsNullOrEmpty(ownerId))
{
sbGuid.Append($"{ownerId.Substring(0, ownerId.Length <= 4 ? ownerId.Length : 4)}-".ToLower());
}
if (!string.IsNullOrEmpty(envId))
{
sbGuid.Append($"{envId.Substring(0, envId.Length <= 4 ? envId.Length : 4)}-".ToLower());
}
if (!string.IsNullOrEmpty(sysId) && sysId.Length > 16)
{
sbGuid.Append($"{sysId.Substring(4, sysId.Length <= 8 ? sysId.Length : 8)}-");
}
else if (!string.IsNullOrEmpty(sysId))
{
sbGuid.Append($"{sysId.Substring(0, sysId.Length <= 8 ? sysId.Length : 8)}-");
}
// 机器码 用于分布式扩展
string guidId = GidSnowflakeGuid(datacenterId);// _configuration.GetValue<string>("snowflake:machineId") ?? "";
//处理字符串问题
sbGuid.Replace("--", "-");
return $"{guidId}-{sbGuid.ToString()}{guid.Substring(0, 36 - sbGuid.Length - guidId.Length - 1)}".Trim('-').PadRight(36, '0');
}
else
{
long machineId = _configuration.GetValue<long>("snowflake:machineId");
GidSnowflakeUtil GidSnowflakeUtil = new GidSnowflakeUtil(machineId, datacenterId);
return GidSnowflakeUtil.GetId().ToString();
}
}
business.json
{
"snowflake": {
"machine": {
"no":false,
//根据环境变量、项目、系统设置机器码
"{envId}{ownerId}{sysId}": 0
}
}
}
号段解析
1bit: 不用,因为二进制中最高位是符号位,1表示负数,0表示正数,生成的id一般都是用整数,所以最高位固定为0.
41bit-时间戳: 用来记录时间戳,毫秒级.41位可以表示2(41)-1个数字;如果只用来表示正整数(计算机中正数包含0),可以表示的数值范围是:0至2(41)-1,减1是因为可表示的数值范围是从0开始算的,而不是1’也就是说41位可以表示2(41)-1个毫秒的值,转化成单位年则是2(41)-1/(1000606024365)=69年(够用到2039-09-07)
10bit-工作机器id: 用来记录工作机器的id.可以部署在2(10)=1024个节点,包括5位datacenterId和5位workerId;5位(bit)可以表示的最大正整数是2(5)-1=31,即可以用0,1,2,3,…31这32个数字,来表示不同的datacenterId和workerId
12bit-序列号: 用来记录同一毫秒内产生的不同id.12位(bit)可以表示最大正整数是2^{12}-1=4095,即可以用0,1,2,3…4094这4095个数字,来表示同一时间戳内产生的4095个ID序号
SnowFlake可以保证: 所有声称的id按时间趋势递增,整个分布式系统内不会产生重复id(因为有datacenterId和workerId来区分)