c#分布式ID生成器

 

简介

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

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

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

代码

    /// <summary>
/// 64位ID生成器,最高位为符号位,始终为0,可用位数63.
/// 实例编号占10位,范围为0-1023
/// 时间戳和索引共占53位
/// </summary>
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;//索引/计数器 /// <summary>
///
/// </summary>
/// <param name="instanceID">实例编号(0-1023)</param>
/// <param name="indexBitLength">索引可用位数(1-32).每秒可生成ID数等于2的indexBitLength次方.大并发情况下,当前秒内ID数达到最大值时,将使用下一秒的时间戳,不影响获取ID.</param>
/// <param name="initTimestamp">初始化时间戳,精确到秒.当之前同一实例生成ID的timestamp值大于当前时间的时间戳时,
/// 有可能会产生重复ID(如持续一段时间的大并发请求).设置initTimestamp比最后的时间戳大一些,可避免这种问题</param>
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;
}
} /// <summary>
/// 默认每实例每秒生成65536个ID,从1970年1月1日起,累计可使用4358年
/// </summary>
/// <param name="instanceID">实例编号(0-1023)</param>
public IdCreator(int instanceID) : this(instanceID, 16)
{ } /// <summary>
/// 默认每秒生成65536个ID,从1970年1月1日起,累计可使用4358年
/// </summary>
public IdCreator() : this(-1)
{ } /// <summary>
/// 生成64位ID
/// </summary>
/// <returns></returns>
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;
} /// <summary>
/// 获取当前实例的时间戳
/// </summary>
public long CurrentTimestamp
{
get
{
return this.timestamp;
}
} /// <summary>
/// 默认每实例每秒生成65536个ID,从1970年1月1日起,累计可使用4358年
/// </summary>
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

c#分布式ID生成器的更多相关文章

  1. 基于redis的分布式ID生成器

    基于redis的分布式ID生成器  

  2. 分布式ID生成器PHP+Swoole实现(上) - 实现原理

    1.发号器介绍 什么是发号器? 全局唯一ID生成器,主要用于分库分表唯一ID,分布式系统数据的唯一标识. 是否需要发号器? 1)是否需要全局唯一. 分布式系统应该不受单点递增ID限制,中心式的会涉及到 ...

  3. go语言实现分布式id生成器

    本文:https://chai2010.cn/advanced-go-programming-book/ch6-cloud/ch6-01-dist-id.html 分布式id生成器 有时我们需要能够生 ...

  4. 分布式ID生成器的解决方案总结

    在互联网的业务系统中,涉及到各种各样的ID,如在支付系统中就会有支付ID.退款ID等.那一般生成ID都有哪些解决方案呢?特别是在复杂的分布式系统业务场景中,我们应该采用哪种适合自己的解决方案是十分重要 ...

  5. 来吧,自己动手撸一个分布式ID生成器组件

    在经过了众多轮的面试之后,小林终于进入到了一家互联网公司的基础架构组,小林目前在公司有使用到架构组研究到分布式id生成器,前一阵子大概看了下其内部的实现,发现还是存在一些架构设计不合理之处.但是又由于 ...

  6. CosId 通用、灵活、高性能的分布式 ID 生成器

    CosId 通用.灵活.高性能的分布式 ID 生成器 介绍 CosId 旨在提供通用.灵活.高性能的分布式系统 ID 生成器. 目前提供了俩大类 ID 生成器:SnowflakeId (单机 TPS ...

  7. CosId 1.0.0 发布,通用、灵活、高性能的分布式 ID 生成器

    CosId 通用.灵活.高性能的分布式 ID 生成器 介绍 CosId 旨在提供通用.灵活.高性能的分布式系统 ID 生成器. 目前提供了俩大类 ID 生成器:SnowflakeId (单机 TPS ...

  8. CosId 1.0.3 发布,通用、灵活、高性能的分布式 ID 生成器

    CosId 通用.灵活.高性能的分布式 ID 生成器 介绍 CosId 旨在提供通用.灵活.高性能的分布式系统 ID 生成器. 目前提供了俩大类 ID 生成器:SnowflakeId (单机 TPS ...

  9. CosId 1.1.0 发布,通用、灵活、高性能的分布式 ID 生成器

    CosId 通用.灵活.高性能的分布式 ID 生成器 介绍 CosId 旨在提供通用.灵活.高性能的分布式系统 ID 生成器. 目前提供了俩大类 ID 生成器:SnowflakeId (单机 TPS ...

随机推荐

  1. 【HNOI 2017】影魔

    Problem Description 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还 ...

  2. js原型和原型链理解到面向对象

    一.js中的两种对象,普通对象和函数对象 var obj1 = {}; var obj2 =new Object(); var obj3 = new obj1(); function fun1(){} ...

  3. JDK内置工具使用

  4. PHP 如何获取客户端ip地址

    PHP 如何获取客户端ip地址 一.总结 一句话总结:主要是使用$_SERVER的 REMOTE_ADDR 和 HTTP_X_FORWARDED_FOR 两个属性,在用户使用不同代理的时候这两个属性可 ...

  5. iview table 实现在数据中自定义标识

    做了一个商旅订票的项目,在详情中有一个因公超标在表格中用一个“超”字显示的需求.后台框架用的iview+vue,也就是在iview Table中改变.在iview的框架中改变东西首先要想到的是ivie ...

  6. spring-boot log

    最近也在研究项目

  7. An overnight dance in discotheque CodeForces - 814D (几何)

    大意: 给定n个不相交的圆, 求将n个圆划分成两部分, 使得阴影部分面积最大. 贪心, 考虑每个连通块, 最外层大圆分成一部分, 剩余分成一部分一定最优. #include <iostream& ...

  8. redis单线程为什么速度那么快?

    1.redis是存储在内存上的,读写的话不会受到硬盘 I/O 速度的限制 如图: (1).硬盘数据库的工作模式: (2).内存数据库的工作模式 2.数据结构简单,对数据操作也简单 3.多路IO复用模型 ...

  9. JS 超类和子类

    此篇由别的大神的博客与<javascript高级程序设计>一书整理而来 原博客地址:https://hyj1254.iteye.com/blog/628555 看到javascript高级 ...

  10. SpringBoot项目中禁用HttpClient那些嘈杂的日志

    在SpringBoot中使用了HttpClient之后,会产生大量嘈杂且基本无效的日志信息,如下图: 找了很多文章,大部分用common-logging.propertites,log4j.prope ...