1 Star 0 Fork 1

flyger/Spw.Snowflake

forked from 星大派/Spw.Snowflake 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
SnowFlakeCore.cs 4.95 KB
一键复制 编辑 原始数据 按行查看 历史
星大派 提交于 2020-11-13 15:16 . init
using System;
namespace Spw.Snowflake
{
public class SnowFlakeCore
{
private static readonly DateTime MIN_DATETIME_UTC = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
/// <summary>
/// 序列号占用位数
/// </summary>
private const int SEQUENCE_BIT = 12;
/// <summary>
/// 机器标识占用位数
/// </summary>
private const int MACHINE_BIT = 5;
/// <summary>
/// 数据中心占用位数
/// </summary>
private const int DATA_CENTER_BIT = 5;
/// <summary>
/// 序列号最大值
/// </summary>
private const long MAX_SEQUENCE = -1 ^ (-1 << SEQUENCE_BIT);
/// <summary>
/// 最大机器标识
/// </summary>
private const long MAX_MACHINE = -1 ^ (-1 << MACHINE_BIT);
/// <summary>
/// 最大数据中心标识
/// </summary>
private const long MAX_DATA_CENTER = -1 ^ (-1 << DATA_CENTER_BIT);
/// <summary>
/// 序列号左移位数
/// </summary>
private const int SEQUENCE_LEFT_OFFSET = 0;
/// <summary>
/// 机器标识左移位数
/// </summary>
private const int MACHINE_LEFT_OFFSET = SEQUENCE_BIT;
/// <summary>
/// 数据中心左移标识
/// </summary>
private const int DATA_CENTER_LEFT_OFFSET = MACHINE_LEFT_OFFSET + MACHINE_BIT;
/// <summary>
/// 时间戳左移标识
/// </summary>
private const int TIMESTAMP_LEFT_OFFSET = DATA_CENTER_LEFT_OFFSET + DATA_CENTER_BIT;
/// <summary>
/// 起始时间戳
/// </summary>
private readonly long START_TIMESTAMP = 0;
/// <summary>
/// 当前数据中心标识
/// </summary>
private long _dataCenterId;
/// <summary>
/// 当前机器标识
/// </summary>
private long _machineId;
/// <summary>
/// 当前序列号
/// </summary>
private long _sequence;
/// <summary>
/// 最后时间戳
/// </summary>
private long _lastTimestamp = -1;
/// <summary>
/// id生成器锁
/// </summary>
private readonly object _mutex = new object();
/// <summary>
///
/// </summary>
/// <param name="startTimeStamp">起始时间戳</param>
/// <param name="dataCenterId">数据中心标识</param>
/// <param name="machineId">机器标识</param>
public SnowFlakeCore(long startTimeStamp, long dataCenterId, long machineId)
{
if (START_TIMESTAMP < 0)
throw new ArgumentOutOfRangeException($"{nameof(startTimeStamp)} must not less than zore");
if (dataCenterId > MAX_DATA_CENTER || dataCenterId < 0)
throw new ArgumentOutOfRangeException($"{nameof(dataCenterId)} must between 0 and {MAX_DATA_CENTER}");
if (machineId > MAX_MACHINE || machineId < 0)
throw new ArgumentOutOfRangeException($"{nameof(machineId)} must between 0 and {MAX_MACHINE}");
START_TIMESTAMP = startTimeStamp;
_dataCenterId = dataCenterId;
_machineId = machineId;
}
/// <summary>
/// 获取时间戳
/// </summary>
/// <returns></returns>
public static long GetUtcTimestamp() => Convert.ToInt64((DateTime.UtcNow - MIN_DATETIME_UTC).TotalMilliseconds);
/// <summary>
/// 获取下一个时间戳
/// </summary>
/// <returns></returns>
private long GetNextTimestamp()
{
var timestamp = GetUtcTimestamp();
for (; timestamp <= _lastTimestamp;)
{
timestamp = GetUtcTimestamp();
}
return timestamp;
}
/// <summary>
/// 生成id
/// </summary>
/// <returns></returns>
public long GenerateId()
{
lock (_mutex)
{
var timestamp = GetUtcTimestamp();
// 时钟被拨回
if (timestamp < _lastTimestamp)
throw new Exception($"Clock moved backwards, refusing to generate id!");
// 相同时间戳,增长序列号
if (timestamp == _lastTimestamp)
{
_sequence = (_sequence + 1) & MAX_SEQUENCE;
if (_sequence == 0)
timestamp = GetNextTimestamp();
}
// 不同时间戳,序列号归零
else
_sequence = 0;
_lastTimestamp = timestamp;
return
(_lastTimestamp - START_TIMESTAMP) << TIMESTAMP_LEFT_OFFSET |
_dataCenterId << DATA_CENTER_LEFT_OFFSET |
_machineId << MACHINE_LEFT_OFFSET |
_sequence;
}
}
}
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C#
1
https://gitee.com/flyger757/spw.-snowflake.git
git@gitee.com:flyger757/spw.-snowflake.git
flyger757
spw.-snowflake
Spw.Snowflake
master

搜索帮助

0d507c66 1850385 C8b1a773 1850385