博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
c#分布式ID生成器
阅读量:6305 次
发布时间:2019-06-22

本文共 2890 字,大约阅读时间需要 9 分钟。

 

简介

这个是根据twitter的来写的.有中文的介绍.

如上图所示,一个64位ID,除了最左边的符号位不用(固定为0,以保证生成的ID都是正数),还剩余63位可用.

下面的代码与图中的位数分配略有不同,除了中间部分10bit工作机器id不变,时间戳和序列号的位数是可以根据自己的需求变化的,就是说,你可以把中间的工作机器ID往左挪一挪,或往右挪一挪.

代码

///     /// 64位ID生成器,最高位为符号位,始终为0,可用位数63. /// 实例编号占10位,范围为0-1023 /// 时间戳和索引共占53位 ///  public sealed class IdCreator { private static readonly Random r = new Random(); private static readonly IdCreator _default = new IdCreator(); private readonly long instanceID;//实例编号 private readonly int indexBitLength;//索引可用位数 private readonly long tsMax = 0;//时间戳最大值 private readonly long indexMax = 0; private readonly object m_lock = new object(); private long timestamp = 0;//当前时间戳 private long index = 0;//索引/计数器 ///  /// ///  /// 实例编号(0-1023) /// 索引可用位数(1-32).每秒可生成ID数等于2的indexBitLength次方.大并发情况下,当前秒内ID数达到最大值时,将使用下一秒的时间戳,不影响获取ID. /// 初始化时间戳,精确到秒.当之前同一实例生成ID的timestamp值大于当前时间的时间戳时, /// 有可能会产生重复ID(如持续一段时间的大并发请求).设置initTimestamp比最后的时间戳大一些,可避免这种问题 public IdCreator(int instanceID, int indexBitLength, long? initTimestamp = null) { if (instanceID < 0) { //这里给每个实例随机生成个实例编号 this.instanceID = r.Next(0, 1024); } else { this.instanceID = instanceID % 1024; } if (indexBitLength < 1) { this.indexBitLength = 1; } else if (indexBitLength > 32) { this.indexBitLength = 32; } else { this.indexBitLength = indexBitLength; } tsMax = Convert.ToInt64(new string('1', 53 - indexBitLength), 2); indexMax = Convert.ToInt64(new string('1', indexBitLength), 2); if (initTimestamp != null) { this.timestamp = initTimestamp.Value; } } ///  /// 默认每实例每秒生成65536个ID,从1970年1月1日起,累计可使用4358年 ///  /// 实例编号(0-1023) public IdCreator(int instanceID) : this(instanceID, 16) { } ///  /// 默认每秒生成65536个ID,从1970年1月1日起,累计可使用4358年 ///  public IdCreator() : this(-1) { } ///  /// 生成64位ID ///  /// 
public long Create() { long id = 0; lock (m_lock) { //增加时间戳部分 long ts = Harry.Common.Utils.GetTimeStamp() / 1000; ts = ts % tsMax; //如果超过时间戳允许的最大值,从0开始 id = ts << (10 + indexBitLength);//腾出后面部分,给实例编号和索引编号使用 //增加实例部分 id = id | (instanceID << indexBitLength); //获取计数 if (timestamp < ts) { timestamp = ts; index = 0; } else { if (index > indexMax) { timestamp++; index = 0; } } id = id | index; index++; } return id; } /// /// 获取当前实例的时间戳 /// public long CurrentTimestamp { get { return this.timestamp; } } /// /// 默认每实例每秒生成65536个ID,从1970年1月1日起,累计可使用4358年 /// public static IdCreator Default { get { return _default; } } }

代码说明

使用时,需要new一个IdCreator的实例,然后调用Create()方法,生成一个ID号.需要把IdCreator的例实赋给一个静态变量,以保证ID号的唯一性.如果是分布式部署,需要给IdCreator的构造函数传递instanceID参数,每一个部署都要有一个不同的值,范围为0-1023.

构造函数中的indexBitLength参数,代表图中最右边的'序列号'的长度,不再固定为12bit,范围为1-32.剩下的可用位,就留给了时间戳.

注意:IdCreator类的时间戳是按秒计的. 如果想改成毫秒,只需要将代码long ts = Harry.Common.Utils.GetTimeStamp() / 1000;改成long ts = Harry.Common.Utils.GetTimeStamp();即可.

示例代码

IdCreator c=new IdCreator(0,16); var id=c.Create(); 转载自:http://www.cnblogs.com/harry-wang/p/6030514.html

转载于:https://www.cnblogs.com/xululublog/p/7047281.html

你可能感兴趣的文章
我的Android进阶之旅------>WindowManager.LayoutParams介绍
查看>>
segment
查看>>
获取鼠标的原始移动值
查看>>
Linux信号 编程
查看>>
有关滚动与位置
查看>>
Box2D自定义重力
查看>>
chpasswd
查看>>
mysqldump --single-transaction 和--lock-tables参数详解
查看>>
android 数据库_sql语句总结
查看>>
python购物车
查看>>
解决python2和python3的pip冲突
查看>>
面试/编程
查看>>
linux每日命令(16):head命令
查看>>
公司内部分享【富有成效的每日站会】总结
查看>>
打造一个上传图片到图床利器的插件(Mac版 开源)
查看>>
iOS横竖屏
查看>>
thinkphp判断更新是否成功
查看>>
Do While ... Loop 与 Do Until ... Loop 的区别
查看>>
【Linux】查询某个字符串出现次数
查看>>
高效使用jquery之一:请使用'On'函数
查看>>