• C# 版本雪花算法(SnowFlake)


    void Main()
     {
     	var id = new XID.Info(271103830593110952);
     	id.Dump();
     }
    
     // You can define other methods, fields, classes and namespaces here
    
    
     public static class XID
     {
     private static long workerId = 0; //机器ID
     private static long sequence = 0L;
     private static long lastTimestamp = -1L;
    
    
     private static readonly int workerIdBits = 10; //机器码字节数。10个字节用来保存机器码(定义为Long类型会出现,最大偏移64位,所以左移64位没有意义)
     private static readonly int sequenceBits = 22 - workerIdBits; //计数器字节数,12个字节用来保存计数码
     private static readonly int sequenceShift = workerIdBits; //机器码数据左移位数,就是后面计数器占用的位数
     private static readonly int timestampLeftShift = sequenceBits + workerIdBits; //时间戳左移动位数就是机器码和计数器总字节数
     private static readonly long workerIdMax = -1L ^ -1L << workerIdBits; //最大WorkId
     private static readonly long sequenceMax = -1L ^ -1L << sequenceBits; //一微秒内可以产生计数,如果达到该值则等到下一微妙在进行生成
     private static readonly object lockObj = new object();
     private static readonly DateTime start_base_time = new DateTime(2020, 1, 1, 0, 0, 0, DateTimeKind.Utc);
    
    
     /// <summary>
     /// 设置机器码
     /// </summary>
     /// <param name="id">机器码</param>
     public static void Initialize(string data)
     {
     	long.TryParse(data, out workerId);
     }
     public static long Nextval
     {
     	get
     	{
     		lock (lockObj)
     		{
     			return nextId();
     		}
     	}
     }
    
     private static long nextId()
     {
     	if (workerId < 1)
     	{
     		workerId = 1982;
     	}
     	workerId = workerId & workerIdMax;
     	long timestamp = timeGen();
     	if (lastTimestamp == timestamp)
     	{
     		//同一微妙中生成ID
     		var abc = (sequence + 1) & sequenceMax; //用&运算计算该微秒内产生的计数是否已经到达上限
     		if (abc == 0)
     		{
     			//一微妙内产生的ID计数已达上限,等待下一微妙
     			timestamp = tillNextMillis(lastTimestamp);
     		}
     		sequence = abc;
     	}
     	else
     	{
     		//不同微秒生成ID
     		sequence = 0; //计数清0
     	}
     	if (timestamp < lastTimestamp)
     	{
     		//如果当前时间戳比上一次生成ID时时间戳还小,抛出异常,因为不能保证现在生成的ID之前没有生成过
     		throw new Exception(string.Format("Clock moved backwards.  Refusing to generate id for {0} milliseconds",
     			lastTimestamp - timestamp));
     	}
     	lastTimestamp = timestamp; //把当前时间戳保存为最后生成ID的时间戳
     	long nextId = timestamp << timestampLeftShift | sequence << sequenceShift | workerId;
     	return nextId;
     }
    
     /// <summary>
     /// 获取下一微秒时间戳
     /// </summary>
     /// <param name="lastTimestamp"></param>
     /// <returns></returns>
     private static long tillNextMillis(long lastTimestamp)
     {
     	long timestamp = timeGen();
     	while (timestamp <= lastTimestamp)
     	{
     		timestamp = timeGen();
     	}
     	return timestamp;
     }
    
    
     /// <summary>
     /// 生成当前时间戳
     /// </summary>
     /// <returns></returns>
     private static long timeGen()
     {
     	return (long)(DateTime.UtcNow - start_base_time).TotalMilliseconds;
     }
     public class Info
     {
     	public Info(long id)
     	{
     		var size = 64;
     		//size = System.Runtime.InteropServices.Marshal.SizeOf(id) * 8;
     		this.Timestamp = id >> timestampLeftShift;
     		this.CreateTime = start_base_time.AddMilliseconds(this.Timestamp);
     		var timeLen = (size - timestampLeftShift);
     		this.SequenceId = id << timeLen >> timeLen >> sequenceShift;
     		this.WorkerId = id & ((1 << sequenceShift) - 1);
     	}
     	public DateTime CreateTime { get; set; }
     	public long Timestamp { get; set; }
     	public long SequenceId { get; set; }
     	public long WorkerId { get; set; }
     }
     }
    
  • 相关阅读:
    爬虫入门---Python2和Python3的不同
    Python学习笔记——文件
    Python字典笔记
    Python列表操作——模拟实现栈和队列
    元组的cmp()内建函数
    Unicode基本概念
    神经网络基本的一些概念
    LLDB调试基本使用
    HTML实现跳转到页面指定位置
    通过pod导入第三方框架
  • 原文地址:https://www.cnblogs.com/urmnur/p/16003631.html
Copyright © 2020-2023  润新知