twitter的snowflake算法(C#版本)
2024-09-24 23:15:03
转自:http://blog.csdn.net/kinwyb/article/details/50238505
使用twitter的snowflake算法生成唯一ID。
在分布式系统中,需要生成全局UID的场合还是比较多的,twitter的snowflake解决了这种需求,实现也还是很简单的,除去配置信息,核心代码就是毫秒级时间41位+机器ID 10位+毫秒内序列12位。
/// <summary>
/// 根据twitter的snowflake算法生成唯一ID
/// snowflake算法 64 位
/// 0---0000000000 0000000000 0000000000 0000000000 0 --- 00000 ---00000 ---000000000000
/// 第一位为未使用(实际上也可作为long的符号位),接下来的41位为毫秒级时间,然后5位datacenter标识位,5位机器ID(并不算标识符,实际是为线程标识),然后12位该毫秒内的当前毫秒内的计数,加起来刚好64位,为一个Long型。
/// 其中datacenter标识位起始是机器位,机器ID其实是线程标识,可以同一一个10位来表示不同机器
/// </summary>
public class IdWorker
{
//机器ID
private static long workerId;
private static long twepoch = 687888001020L; //唯一时间,这是一个避免重复的随机量,自行设定不要大于当前时间戳
private static long sequence = 0L;
private static int workerIdBits = ; //机器码字节数。4个字节用来保存机器码
public static long maxWorkerId = -1L ^ -1L << workerIdBits; //最大机器ID
private static int sequenceBits = ; //计数器字节数,10个字节用来保存计数码
private static int workerIdShift = sequenceBits; //机器码数据左移位数,就是后面计数器占用的位数
private static int timestampLeftShift = sequenceBits + workerIdBits; //时间戳左移动位数就是机器码和计数器总字节数
public static long sequenceMask = -1L ^ -1L << sequenceBits; //一微秒内可以产生计数,如果达到该值则等到下一微妙在进行生成
private long lastTimestamp = -1L; public IdWorker(long workerId)
{
if (workerId > maxWorkerId || workerId < )
throw new Exception(string.Format("worker Id can't be greater than {0} or less than 0 ", workerId));
IdWorker.workerId=workerId;
} public long nextId()
{
lock (this)
{
long timestamp = timeGen();
if(this.lastTimestamp == timestamp){ //同一微妙中生成ID
IdWorker.sequence = (IdWorker.sequence + ) & IdWorker.sequenceMask; //用&运算计算该微秒内产生的计数是否已经到达上限
if(IdWorker.sequence == ){
//一微妙内产生的ID计数已达上限,等待下一微妙
timestamp = tillNextMillis(this.lastTimestamp);
}
}
else{ //不同微秒生成ID
IdWorker.sequence = ; //计数清0
}
if(timestamp < lastTimestamp)
{ //如果当前时间戳比上一次生成ID时时间戳还小,抛出异常,因为不能保证现在生成的ID之前没有生成过
throw new Exception(string.Format("Clock moved backwards. Refusing to generate id for {0} milliseconds",
this.lastTimestamp - timestamp));
}
this.lastTimestamp = timestamp; //把当前时间戳保存为最后生成ID的时间戳
long nextId = (timestamp - twepoch << timestampLeftShift) | IdWorker.workerId << IdWorker.workerIdShift | IdWorker.sequence;
return nextId;
}
} /// <summary>
/// 获取下一微秒时间戳
/// </summary>
/// <param name="lastTimestamp"></param>
/// <returns></returns>
private long tillNextMillis(long lastTimestamp)
{
long timestamp = timeGen();
while(timestamp <= lastTimestamp)
{
timestamp = timeGen();
}
return timestamp;
} /// <summary>
/// 生成当前时间戳
/// </summary>
/// <returns></returns>
private long timeGen()
{
return (long)(DateTime.UtcNow - new DateTime(, , , , , , DateTimeKind.Utc)).TotalMilliseconds;
} }
最新文章
- Entity Framework 6 Recipes 2nd Edition(11-9)译 ->; 在LINQ中使用规范函数
- MVVM下listbox默认显示最后一行
- 软件产品案例分析----K米app
- Hadoop: Hadoop Cluster配置文件
- MVC 4 异步编程简化了
- [问题2014S13] 解答
- Angular系列---- AngularJS入门教程03:AngularJS 模板(转载)
- 【现代程序设计】homework-04
- Altiium Designer 09 解决局域网冲突的办法(转载)
- json 说明书
- 对象、对象数组、JSON、JSON数组的相关操作
- IoC/DIP其实是一种管理思想
- 关闭Windows 2008下面应用程序出错后的提示
- JS设计模式---缓存代理
- python重试(指数退避算法)
- 【CF 678F】Lena and Queries
- 学号 20175329 2018-2019-3《Java程序设计》第六周学习总结
- JSP_tomcat_mysql_注冊验证用户;
- P750 内存插槽
- 【比赛游记】NOIP2017游记
热门文章
- java.io.IOException: Cannot run program ";bash";: error=12, Cannot allocate memory
- hdu 3715
- 1089-Duplicate Removal
- 利用动软代码生成器 自动生成LINQ需要用的数据实体类 (转)
- DHTMLX 前端框架 建立你的一个应用程序 教程(九)--绑定表单Form到表格Grrid中
- 【HDOJ】1075 What Are You Talking About
- How to: Implement a Windows Communication Foundation Service Contract
- NTP 服务器配置
- WCF 第五章 会话级别的实例
- CONTAINING_RECORD 宏