参考地址:https://blog.csdn.net/w200221626/article/details/52064976

 /// <summary>
/// 动态生产有规律的ID
/// </summary>
public class Snowflake
{
private static long machineId;//机器ID
private static long datacenterId = 0L;//数据ID
private static long sequence = 0L;//计数从零开始 private static long twepoch = 687888001020L; //唯一时间随机量 private static long machineIdBits = 5L; //机器码字节数
private static long datacenterIdBits = 5L;//数据字节数
public static long maxMachineId = -1L ^ -1L << (int)machineIdBits; //最大机器ID
private static long maxDatacenterId = -1L ^ (-1L << (int)datacenterIdBits);//最大数据ID private static long sequenceBits = 12L; //计数器字节数,12个字节用来保存计数码
private static long machineIdShift = sequenceBits; //机器码数据左移位数,就是后面计数器占用的位数
private static long datacenterIdShift = sequenceBits + machineIdBits;
private static long timestampLeftShift = sequenceBits + machineIdBits + datacenterIdBits; //时间戳左移动位数就是机器码+计数器总字节数+数据字节数
public static long sequenceMask = -1L ^ -1L << (int)sequenceBits; //一微秒内可以产生计数,如果达到该值则等到下一微妙在进行生成
private static long lastTimestamp = -1L;//最后时间戳 private static object syncRoot = new object();//加锁对象
static Snowflake snowflake; public static Snowflake Instance()
{
if (snowflake == null)
snowflake = new Snowflake();
return snowflake;
} public Snowflake()
{
Snowflakes(0L, -);
} public Snowflake(long machineId)
{
Snowflakes(machineId, -);
} public Snowflake(long machineId, long datacenterId)
{
Snowflakes(machineId, datacenterId);
} private void Snowflakes(long machineId, long datacenterId)
{
if (machineId >= )
{
if (machineId > maxMachineId)
{
throw new Exception("机器码ID非法");
}
Snowflake.machineId = machineId;
}
if (datacenterId >= )
{
if (datacenterId > maxDatacenterId)
{
throw new Exception("数据中心ID非法");
}
Snowflake.datacenterId = datacenterId;
}
} /// <summary>
/// 生成当前时间戳
/// </summary>
/// <returns>毫秒</returns>
private static long GetTimestamp()
{
return (long)(DateTime.UtcNow - new DateTime(, , , , , , DateTimeKind.Utc)).TotalMilliseconds;
} /// <summary>
/// 获取下一微秒时间戳
/// </summary>
/// <param name="lastTimestamp"></param>
/// <returns></returns>
private static long GetNextTimestamp(long lastTimestamp)
{
long timestamp = GetTimestamp();
if (timestamp <= lastTimestamp)
{
timestamp = GetTimestamp();
}
return timestamp;
} /// <summary>
/// 获取长整形的ID
/// </summary>
/// <returns></returns>
public long GetId()
{
lock (syncRoot)
{
long timestamp = GetTimestamp();
if (Snowflake.lastTimestamp == timestamp)
{ //同一微妙中生成ID
sequence = (sequence + ) & sequenceMask; //用&运算计算该微秒内产生的计数是否已经到达上限
if (sequence == )
{
//一微妙内产生的ID计数已达上限,等待下一微妙
timestamp = GetNextTimestamp(Snowflake.lastTimestamp);
}
}
else
{
//不同微秒生成ID
sequence = 0L;
}
if (timestamp < lastTimestamp)
{
throw new Exception("时间戳比上一次生成ID时时间戳还小,故异常");
}
Snowflake.lastTimestamp = timestamp; //把当前时间戳保存为最后生成ID的时间戳
long Id = ((timestamp - twepoch) << (int)timestampLeftShift)
| (datacenterId << (int)datacenterIdShift)
| (machineId << (int)machineIdShift)
| sequence;
return Id;
} }
}

测试代码:

class Program
{
static void Main(string[] args)
{
var blockingCollection = new BlockingCollection<long>();
List<Task> tasks = new List<Task>();
for (int i = ; i < ; i++)
{
var task = Task.Run(() =>
{ for (int j = ; j < ; j++)
{ //blockingCollection.Add(Snowflake.Instance().GetId());//一台机器 blockingCollection.Add(new Snowflake(,).GetId());//多台机器
}
}); tasks.Add(task);
} Task.WaitAll(tasks.ToArray()); Console.WriteLine(blockingCollection.Distinct().Count()); Console.ReadKey(); }
}

github:https://github.com/RobThree/IdGen

C# 实现 Snowflake算法生成唯一性Id的更多相关文章

  1. 根据twitter的snowflake算法生成唯一ID

    C#版本 /// <summary> /// 根据twitter的snowflake算法生成唯一ID /// snowflake算法 64 位 /// 0---0000000000 000 ...

  2. C# 根据twitter的snowflake算法生成唯一ID

    C# 版算法: using System; using System.Collections.Generic; using System.Linq; using System.Text; using ...

  3. PHP使用SnowFlake算法生成唯一ID

    前言:最近需要做一套CMS系统,由于功能比较单一,而且要求灵活,所以放弃了WP这样的成熟系统,自己做一套相对简单一点的.文章的详情页URL想要做成url伪静态的格式即xxx.html 其中xxx考虑过 ...

  4. 关于snowflake算法生成的ID转换为JS的数字类型由于过大导致JS精度丢失的问题

    JS的数字类型目前支持的最大值为:9007199254740992,一旦数字超过这个值,JS将会丢失精度,导致前后端的值出现不一致. JAVA的Long类型的       最大值为:922337203 ...

  5. 使用SnowFlake算法生成唯一ID

    转自:https://segmentfault.com/a/1190000007769660 考虑过的方法有 直接用时间戳,或者以此衍生的一系列方法 Mysql自带的uuid 以上两种方法都可以查到就 ...

  6. 封装各种生成唯一性ID算法的工具类

    /** * Copyright (c) 2005-2012 springside.org.cn * * Licensed under the Apache License, Version 2.0 ( ...

  7. 基于雪花算法生成分布式ID(Java版)

    SnowFlake算法原理介绍 在分布式系统中会将一个业务的系统部署到多台服务器上,用户随机访问其中一台,而之所以引入分布式系统就是为了让整个系统能够承载更大的访问量.诸如订单号这些我们需要它是全局唯 ...

  8. 雪花算法生成分布式ID

    分布式主键ID生成方案 分布式主键ID的生成方案有以下几种: 数据库自增主键 缺点: 导入旧数据时,可能会ID重复,导致导入失败 分布式架构,多个Mysql实例可能会导致ID重复 UUID 缺点: 占 ...

  9. Java 利用 UUID 生成唯一性 ID 示例代码

    用户ID首先生成,订单ID的生成可依赖用户ID. 下面代码前六位是日期,后八位是随机数,用于生成用户ID. public String getNewUserId() { String ipAddres ...

随机推荐

  1. centos7下关闭sshd的tcp6

    问题现象 不算问题,就是偶然发现新装好的系统默认的sshd服务启动后的监听项有2个,如下图: 想着自己已经明明关闭了ipv6,竟然还起这tcp6...,强迫症犯了,尝试关闭它,百度一眼几乎没有,记录一 ...

  2. 第二篇--上传git 代码

    准备工作: 首先,注册一个GitHub账号. 接着,新建一个仓库. 最后,下载Git 上传代码步骤: 第一步,新建一个本地文件夹作为本地仓库,进入该文件夹. 右击选择Git Bash Here ,输入 ...

  3. 第四十六篇--解析和保存xml文件

    新建assets资源文件夹,右键app --> new --> Folder --> Assets Folder,将info.xml放入此文件夹下面. info.xml <?x ...

  4. jvm经典文章整理

    Java中JVM虚拟机详解 Java GC的那些事(上)(博主还有很多文章都很经典) CMS垃圾收集器介绍

  5. SQLServer2012基于扩展事件的阻塞监控

    一.前言 SQL阻塞Block是事务联机系统OLTP的产物.由于锁导致的资源等待,事务执行时间过长,直接影响业务:了解阻塞,发现阻塞,已作为DBA日常维护的重中之重. 通过dmv可以发现当前正在阻塞的 ...

  6. jQuery循环遍历取值

    1:循环遍历取值 var arr = new Array(); $(".plus-tag a span").each(function(i) { arr[i] = $(this). ...

  7. Groovy中的GString

    在讨论GString之前,我们先讨论一下Groovy里面的String.在Groovy里面String有 println 'test string' println '''test string''' ...

  8. redis集群配置与管理

    Redis在3.0版本以后开始支持集群,经过中间几个版本的不断更新优化,最新的版本集群功能已经非常完善.本文简单介绍一下Redis集群搭建的过程和配置方法,redis版本是5.0.4,操作系统是中标麒 ...

  9. XSS,CSRF,Cookie防劫持的处理

    Cookie与sessionHTTP天然是无状态的协议, 为了维持和跟踪用户的状态, 引入了Cookie和Session. Cookie包含了浏览器客户端的用户凭证, 相对较小. Session则维护 ...

  10. JAVA进阶21

    1.Vector向量 如何选用ArrayList.LinkedList.Vector? ①需要线程安全时,用Vector ②不存在线程安全问题时,并且查找较多用ArrayList(一般使用它) ③不存 ...