转自: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;
} }

最新文章

  1. Entity Framework 6 Recipes 2nd Edition(11-9)译 -&gt; 在LINQ中使用规范函数
  2. MVVM下listbox默认显示最后一行
  3. 软件产品案例分析----K米app
  4. Hadoop: Hadoop Cluster配置文件
  5. MVC 4 异步编程简化了
  6. [问题2014S13] 解答
  7. Angular系列---- AngularJS入门教程03:AngularJS 模板(转载)
  8. 【现代程序设计】homework-04
  9. Altiium Designer 09 解决局域网冲突的办法(转载)
  10. json 说明书
  11. 对象、对象数组、JSON、JSON数组的相关操作
  12. IoC/DIP其实是一种管理思想
  13. 关闭Windows 2008下面应用程序出错后的提示
  14. JS设计模式---缓存代理
  15. python重试(指数退避算法)
  16. 【CF 678F】Lena and Queries
  17. 学号 20175329 2018-2019-3《Java程序设计》第六周学习总结
  18. JSP_tomcat_mysql_注冊验证用户;
  19. P750 内存插槽
  20. 【比赛游记】NOIP2017游记

热门文章

  1. java.io.IOException: Cannot run program &quot;bash&quot;: error=12, Cannot allocate memory
  2. hdu 3715
  3. 1089-Duplicate Removal
  4. 利用动软代码生成器 自动生成LINQ需要用的数据实体类 (转)
  5. DHTMLX 前端框架 建立你的一个应用程序 教程(九)--绑定表单Form到表格Grrid中
  6. 【HDOJ】1075 What Are You Talking About
  7. How to: Implement a Windows Communication Foundation Service Contract
  8. NTP 服务器配置
  9. WCF 第五章 会话级别的实例
  10. CONTAINING_RECORD 宏