概述
分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移到Cassandra,因为Cassandra没有顺序ID生成机制,所以开发了这样一套全局唯一ID生成服务。
该项目地址为:https://github.com/twitter/snowflake是用Scala实现的。
python版详见开源项目https://github.com/erans/pysnowflake。

结构
snowflake的结构如下(每部分用-分开):

0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000

第一位为未使用,接下来的41位为毫秒级时间(41位的长度可以使用69年),然后是5位datacenterId和5位workerId(10位的长度最多支持部署1024个节点) ,最后12位是毫秒内的计数(12位的计数顺序号支持每个节点每毫秒产生4096个ID序号)

一共加起来刚好64位,为一个Long型。(转换成字符串长度为18)

snowflake生成的ID整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由datacenter和workerId作区分),并且效率较高。据说:snowflake每秒能够产生26万个ID。

源码(C#版本源码)

  1. public class IdWorker
  2. {
  3. //机器ID
  4. private static long workerId;
  5. private static long twepoch = 687888001020L; //唯一时间,这是一个避免重复的随机量,自行设定不要大于当前时间戳
  6. private static long sequence = 0L;
  7. private static int workerIdBits = ; //机器码字节数。4个字节用来保存机器码(定义为Long类型会出现,最大偏移64位,所以左移64位没有意义)
  8. public static long maxWorkerId = -1L ^ -1L << workerIdBits; //最大机器ID
  9. private static int sequenceBits = ; //计数器字节数,10个字节用来保存计数码
  10. private static int workerIdShift = sequenceBits; //机器码数据左移位数,就是后面计数器占用的位数
  11. private static int timestampLeftShift = sequenceBits + workerIdBits; //时间戳左移动位数就是机器码和计数器总字节数
  12. public static long sequenceMask = -1L ^ -1L << sequenceBits; //一微秒内可以产生计数,如果达到该值则等到下一微妙在进行生成
  13. private long lastTimestamp = -1L;
  14.  
  15. /// <summary>
  16. /// 机器码
  17. /// </summary>
  18. /// <param name="workerId"></param>
  19. public IdWorker(long workerId)
  20. {
  21. if (workerId > maxWorkerId || workerId < )
  22. throw new Exception(string.Format("worker Id can't be greater than {0} or less than 0 ", workerId));
  23. IdWorker.workerId = workerId;
  24. }
  25.  
  26. public long nextId()
  27. {
  28. lock (this)
  29. {
  30. long timestamp = timeGen();
  31. if (this.lastTimestamp == timestamp)
  32. { //同一微妙中生成ID
  33. IdWorker.sequence = (IdWorker.sequence + ) & IdWorker.sequenceMask; //用&运算计算该微秒内产生的计数是否已经到达上限
  34. if (IdWorker.sequence == )
  35. {
  36. //一微妙内产生的ID计数已达上限,等待下一微妙
  37. timestamp = tillNextMillis(this.lastTimestamp);
  38. }
  39. }
  40. else
  41. { //不同微秒生成ID
  42. IdWorker.sequence = ; //计数清0
  43. }
  44. if (timestamp < lastTimestamp)
  45. { //如果当前时间戳比上一次生成ID时时间戳还小,抛出异常,因为不能保证现在生成的ID之前没有生成过
  46. throw new Exception(string.Format("Clock moved backwards. Refusing to generate id for {0} milliseconds",
  47. this.lastTimestamp - timestamp));
  48. }
  49. this.lastTimestamp = timestamp; //把当前时间戳保存为最后生成ID的时间戳
  50. long nextId = (timestamp - twepoch << timestampLeftShift) | IdWorker.workerId << IdWorker.workerIdShift | IdWorker.sequence;
  51. return nextId;
  52. }
  53. }
  54.  
  55. /// <summary>
  56. /// 获取下一微秒时间戳
  57. /// </summary>
  58. /// <param name="lastTimestamp"></param>
  59. /// <returns></returns>
  60. private long tillNextMillis(long lastTimestamp)
  61. {
  62. long timestamp = timeGen();
  63. while (timestamp <= lastTimestamp)
  64. {
  65. timestamp = timeGen();
  66. }
  67. return timestamp;
  68. }
  69.  
  70. /// <summary>
  71. /// 生成当前时间戳
  72. /// </summary>
  73. /// <returns></returns>
  74. private long timeGen()
  75. {
  76. return (long)(DateTime.UtcNow - new DateTime(, , , , , , DateTimeKind.Utc)).TotalMilliseconds;
  77. }
  78.  
  79. }

调用方法:

  1. IdWorker idworker = new IdWorker();
  2. for (int i = ; i < ; i++)
  3. {
  4. Response.Write(idworker.nextId() + "<br/>");
  5. }

转自:https://blog.csdn.net/u011872945/article/details/54562213

Twitter的分布式自增ID算法snowflake(雪花算法) - C#版的更多相关文章

  1. 详解Twitter开源分布式自增ID算法snowflake(附演算验证过程)

    详解Twitter开源分布式自增ID算法snowflake,附演算验证过程 2017年01月22日 14:44:40 url: http://blog.csdn.net/li396864285/art ...

  2. 分布式ID生成器 snowflake(雪花)算法

    在springboot的启动类中引入 @Bean public IdWorker idWorkker(){ return new IdWorker(1, 1); } 在代码中调用 @Autowired ...

  3. Twitter的分布式自增ID算法snowflake

    snowflake 分布式场景下获取自增id git:https://github.com/twitter/snowflake 解读: http://www.cnblogs.com/relucent/ ...

  4. 分布式主键解决方案之--Snowflake雪花算法

    0--前言 对于分布式系统环境,主键ID的设计很关键,什么自增intID那些是绝对不用的,比较早的时候,大部分系统都用UUID/GUID来作为主键,优点是方便又能解决问题,缺点是插入时因为UUID/G ...

  5. Twitter的分布式自增ID算法snowflake (Java版)

    概述 分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的. 有些时候我们希望能使用一种 ...

  6. UUID实现之一twitter的分布式自增IDsnowflake算法

    Twitter的分布式自增ID算法snowflake (Java版)   概述 分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点 ...

  7. Twitter分布式自增ID算法snowflake原理解析

    以JAVA为例 Twitter分布式自增ID算法snowflake,生成的是Long类型的id,一个Long类型占8个字节,每个字节占8比特,也就是说一个Long类型占64个比特(0和1). 那么一个 ...

  8. Twitter分布式自增ID算法snowflake原理解析(Long类型)

    Twitter分布式自增ID算法snowflake,生成的是Long类型的id,一个Long类型占8个字节,每个字节占8比特,也就是说一个Long类型占64个比特(0和1). 那么一个Long类型的6 ...

  9. 分布式自增ID算法-Snowflake详解

    1.Snowflake简介 互联网快速发展的今天,分布式应用系统已经见怪不怪,在分布式系统中,我们需要各种各样的ID,既然是ID那么必然是要保证全局唯一,除此之外,不同当业务还需要不同的特性,比如像并 ...

随机推荐

  1. matlab 高级函数 —— colfilt/blockproc (图像)矩阵的分块处理

    colfilt 执行功能与 blockproc/nlfilter 类似,但效率更高. B = colfilt(A,[m n],block_type,fun),block_type:distinct/s ...

  2. Numpy Usage Introduction

    Reference : http://my.oschina.net/u/175377/blog/74406 试验性的Numpy教程 原文来自Tentative NumPy Tutorial 目录 先决 ...

  3. visual studio 编译器在辨异 C/C++ 程序时的注意事项

    1. 数组大小的限制 visual studio 对数组的维数(元素的个数)没有限制,但要求数组的 size (sizeof() 后的结果,所占内存的大小)不得超过 0x7fff ffff = 2^3 ...

  4. this prototype constructor

    http://www.cnblogs.com/phpmix/articles/1734031.html

  5. QWidget居中显示(qt窗口坐标原点是在”左上角”的,有图)

    转载请说明出处, 并附上原文链接http://blog.csdn.net/qq907482638/article/details/72189014. 问题描述 在Qt学习过程中,在让QDialog居中 ...

  6. Android TV开发总结(七)构建一个TV app中的剧集列表控件

    原文:Android TV开发总结(七)构建一个TV app中的剧集列表控件 版权声明:我已委托"维权骑士"(rightknights.com)为我的文章进行维权行动.转载务必转载 ...

  7. Cocos2d-x 3.1 一步一步地做改编

    本文并不想谈论的屏幕改编或真理的概念.假设不知道cocos2d-x的,请先看这篇文章:http://www.cocoachina.com/gamedev/cocos/2014/0516/8451.ht ...

  8. 受限玻尔兹曼机(RBM)以及对比散度(CD)

    1. RBM 的提出 BM 的缺点: 计算时间漫长,尤其是无约束自由迭代的负向阶段: 对抽样噪音敏感: 流行软件的不支持: 受限玻尔兹曼机(Restricted Boltzmann Machine,简 ...

  9. IME输入法编程心得

    原文:IME输入法编程心得 posted @ 2012-11-30 00:42 from [FreedomShe] 自然语言处理的输入法作业成品没有做出来,但不想再在蛋疼的Win32上面耗费时间了,整 ...

  10. springboot 修改连接地址和端口

    spring boot 默认 http://localhost:8080 修改为本地IP地址和修改端口在application.properties中添加以下: server.port=9090 se ...