1. public class IdWorker
  2. {
  3. //基准时间
  4. public const long Twepoch = 1288834974657L;
  5.  
  6. //机器标识位数
  7. private const int WorkerIdBits = ;
  8.  
  9. //数据标志位数
  10. private const int DatacenterIdBits = ;
  11.  
  12. //序列号识位数
  13. private const int SequenceBits = ;
  14.  
  15. //机器ID最大值
  16. private const long MaxWorkerId = -1L ^ (-1L << WorkerIdBits);
  17.  
  18. //数据标志ID最大值
  19. private const long MaxDatacenterId = -1L ^ (-1L << DatacenterIdBits);
  20.  
  21. //序列号ID最大值
  22. private const long SequenceMask = -1L ^ (-1L << SequenceBits);
  23.  
  24. //机器ID偏左移10位
  25. private const int WorkerIdShift = SequenceBits;
  26.  
  27. //数据ID偏左移15位
  28. private const int DatacenterIdShift = SequenceBits + WorkerIdBits;
  29.  
  30. //时间毫秒左移20位
  31. public const int TimestampLeftShift = SequenceBits + WorkerIdBits + DatacenterIdBits;
  32.  
  33. private static readonly DateTime Jan1St1970 = new DateTime
  34. (, , , , , , DateTimeKind.Utc);
  35.  
  36. private readonly object _lock = new object();
  37. private long _lastTimestamp = -1L;
  38.  
  39. public IdWorker(long workerId, long datacenterId, long sequence = 0L)
  40. {
  41. // 如果超出范围就抛出异常
  42. if (workerId > MaxWorkerId || workerId < )
  43. throw new ArgumentException(string.Format("worker Id 必须大于0,且不能大于MaxWorkerId: {0}", MaxWorkerId));
  44.  
  45. if (datacenterId > MaxDatacenterId || datacenterId < )
  46. throw new ArgumentException(string.Format("datacenterId Id 必须大于0,且不能大于MaxWorkerId: {0}",
  47. MaxDatacenterId));
  48.  
  49. //先检验再赋值
  50. WorkerId = workerId;
  51. DatacenterId = datacenterId;
  52. Sequence = sequence;
  53. }
  54.  
  55. public long WorkerId { get; protected set; }
  56. public long DatacenterId { get; protected set; }
  57.  
  58. public long Sequence { get; internal set; }
  59.  
  60. public virtual long NextId(long dataNode=)
  61. {
  62. lock (_lock)
  63. {
  64. if (dataNode > MaxDatacenterId || dataNode < )
  65. throw new ArgumentException($"dataNode 必须大于0,且不能大于MaxWorkerId: {MaxDatacenterId}");
  66. if (dataNode == )
  67. dataNode = DatacenterId;
  68. var timestamp = TimeGen();
  69. if (timestamp < _lastTimestamp)
  70. throw new Exception($"时间戳必须大于上一次生成ID的时间戳. 拒绝为{_lastTimestamp - timestamp}毫秒生成id");
  71.  
  72. //如果上次生成时间和当前时间相同,在同一毫秒内
  73. if (_lastTimestamp == timestamp)
  74. {
  75. //sequence自增,和sequenceMask相与一下,去掉高位
  76. Sequence = (Sequence + ) & SequenceMask;
  77. //判断是否溢出,也就是每毫秒内超过1024,当为1024时,与sequenceMask相与,sequence就等于0
  78. if (Sequence == )
  79. timestamp = TilNextMillis(_lastTimestamp);
  80. }
  81. else
  82. {
  83. //如果和上次生成时间不同,重置sequence,就是下一毫秒开始,sequence计数重新从0开始累加,
  84. //为了保证尾数随机性更大一些,最后一位可以设置一个随机数
  85. Sequence = ; //new Random().Next(10);
  86. }
  87.  
  88. _lastTimestamp = timestamp;
  89. return ((timestamp - Twepoch) << TimestampLeftShift) | (dataNode << DatacenterIdShift) |
  90. (WorkerId << WorkerIdShift) | Sequence;
  91. }
  92. }
  93.  
  94. /// <summary>
  95. /// 防止产生的时间比之前的时间还要小(由于NTP回拨等问题),保持增量的趋势.
  96. /// </summary>
  97. /// <param name="lastTimestamp"></param>
  98. /// <returns></returns>
  99. protected virtual long TilNextMillis(long lastTimestamp)
  100. {
  101. var timestamp = TimeGen();
  102. while (timestamp <= lastTimestamp)
  103. timestamp = TimeGen();
  104. return timestamp;
  105. }
  106.  
  107. /// <summary>
  108. /// 获取当前的时间戳
  109. /// </summary>
  110. /// <returns></returns>
  111. protected virtual long TimeGen()
  112. {
  113. return (long) (DateTime.UtcNow - Jan1St1970).TotalMilliseconds;
  114. }
  115. }
  1. public void GetId()
  2. {
  3. new IdWorker(, ).NextId();
  4. }

关于分布式环境下的id生成的更多相关文章

  1. 分布式环境下的id生成方法

    分布式环境下的id生成方法   前几天研究数据库分表分库的问题,其中有一个关键的地方就是生成唯一键的问题,假如数据表有1亿条数据,而且还在不断的增加,这里我们就需要考虑到分表分库,假设我们采用Hash ...

  2. 分布式环境下Unique ID生成方法

    ID即标示符,在某个搜索域内能唯一标示其中某个对象.在关系型数据库中每个表都需要定义一个主键来唯一标示一条记录.为了方便一般都会使用一个auto_increment属性的整形数做为ID.因为数据库本身 ...

  3. 【融云分析】如何实现分布式场景下唯一 ID 生成?

    ◀背景▶ 对于一套分布式部署的 IM 系统,要求每条消息的 ID 要保证在集群中全局唯一且按生成时间有序排列.如何快速高效的生成消息数据的唯一 ID ,是影响系统吞吐量的关键因素.那么,融云是如何做到 ...

  4. MySQL分库分表环境下全局ID生成方案 转

    在大型互联网应用中,随着用户数的增加,为了提高应用的性能,我们经常需要对数据库进行分库分表操作.在单表时代,我们可以完全依赖于数据库的自增ID来唯一标识一个用户或数据对象.但是当我们对数据库进行了分库 ...

  5. MySQL分库分表环境下全局ID生成方案

    在大型互联网应用中,随着用户数的增加,为了提高应用的性能,我们经常需要对数据库进行分库分表操作.在单表时代,我们可以完全依赖于数据库的自增ID来唯一标识一个用户或数据对象.但是当我们对数据库进行了分库 ...

  6. 【转】MySQL分库分表环境下全局ID生成方案

    转载一篇博客,里面有很多的知识和思想值得我们去思考. —————————————————————————————————————————————————————————————————————— 在大 ...

  7. 高并发环境下全局id生成策略

    解决方案: 基于Redis的全局id生成策略:(推荐此方法) 基于雪花算法的全局id生成: https://www.cnblogs.com/kobe-qi/p/8761690.html 基于zooke ...

  8. Shiro权限管理框架(二):Shiro结合Redis实现分布式环境下的Session共享

    首发地址:https://www.guitu18.com/post/2019/07/28/44.html 本篇是Shiro系列第二篇,使用Shiro基于Redis实现分布式环境下的Session共享. ...

  9. 分布式全局不重复ID生成算法

    分布式全局不重复ID生成算法 算法全局id唯一id  在分布式系统中经常会使用到生成全局唯一不重复ID的情况.本篇博客介绍生成的一些方法. 常见的一些方式: 1.通过DB做全局自增操作 优点:简单.高 ...

随机推荐

  1. [原创] f2fs文件系统源代码分析 —— 基于3.8内核 (一)

    作者:高翔 <esxgx@163.com>本文著作权归作者所有,请在转载引用时保留原文网址. 在全文开始,首先记录f2fs被3.8主线merge的mailing list:[GIT PUL ...

  2. luoguP1373 小a和uim之大逃离

    DP专题 题目链接 思路 \(f[i][j][a][b][0/1]\)表示在\((i,j)\)这个格子,小a有a滴魔液,他的伙伴有b滴,上一步是小a(0)或者他的伙伴(1)吸取的魔液. (显然)数组开 ...

  3. webstorm Terminal 位置错乱解决方案

    win+R 打开终端,右击属性->勾选使用旧版控制台->确定 ,再重启webstrom 即可.

  4. Restful 接口开发 完整版

    准备: springboot ssm框架 项目结构:注意 Swagger2Config要和springboot的启动类放在同一级 //pom所需的依赖 <dependency> <g ...

  5. The Quad - Directory Explorer(一款四窗口的文件资源管理器)

    官网:http://www.q-dir.com/ 参考这位兄弟的介绍:https://www.cnblogs.com/clso/p/4694486.html 一款四窗口的文件资源管理器.

  6. memcpy一种实现方法

    #include<stdio.h> #include<stdlib.h> void* memncpy(void* dest, const void* src, int coun ...

  7. A页面跳转到B页面后打开指定tabs标签

    A页面: <!DOCTYPE html><html lang="en" class="no-js">    <head>   ...

  8. maven安装与环境变量配置

    一.什么是maven Maven基于项目对象模型(POM Project Object Model),可以通过一小段描述信息(配置文件)来管理项目的构建.报告和文档的软件项目管理工具. 同时也是跨平台 ...

  9. 解决MongoDB登录的WARNING

    解决MongoDB登录的WARNING 1.安装完成运行mongodb警告内容如下: 2019-01-17T15:41:50.578+0800 I CONTROL [initandlisten] ** ...

  10. Linux网络技术管理及进程管理

    OSI七层模型和TCP/IP四层模型 OSI七层模型:OSI(Open System Interconnection)开放系统互连参考模型是国际标准化组织(ISO)制定的一个用于计算机或通信系统间互联 ...