http://blog.csdn.net/w200221626/article/details/52064976

C# 实现 Snowflake算法

/// <summary>
/// 动态生产有规律的ID Snowflake算法是Twitter的工程师为实现递增而不重复的ID实现的
/// http://blog.csdn.net/w200221626/article/details/52064976
/// C# 实现 Snowflake算法
/// </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, -1);
} public Snowflake(long machineId)
{
Snowflakes(machineId, -1);
} public Snowflake(long machineId, long datacenterId)
{
Snowflakes(machineId, datacenterId);
} private void Snowflakes(long machineId, long datacenterId)
{
if (machineId >= 0)
{
if (machineId > maxMachineId)
{
throw new Exception("机器码ID非法");
}
Snowflake.machineId = machineId;
}
if (datacenterId >= 0)
{
if (datacenterId > maxDatacenterId)
{
throw new Exception("数据中心ID非法");
}
Snowflake.datacenterId = datacenterId;
}
} /// <summary>
/// 生成当前时间戳
/// </summary>
/// <returns>毫秒</returns>
private static long GetTimestamp()
{
//让他2000年开始
return (long)(DateTime.UtcNow - new DateTime(2000, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds;
} /// <summary>
/// 获取下一微秒时间戳
/// </summary>
/// <param name="lastTimestamp"></param>
/// <returns></returns>
private static long GetNextTimestamp(long lastTimestamp)
{
long timestamp = GetTimestamp();
int count = 0;
while (timestamp <= lastTimestamp)//这里获取新的时间,可能会有错,这算法与comb一样对机器时间的要求很严格
{
count++;
if (count > 10)
throw new Exception("机器的时间可能不对");
Thread.Sleep(1);
timestamp = GetTimestamp();
}
return timestamp;
} /// <summary>
/// 获取长整形的ID
/// </summary>
/// <returns></returns>
public long GetId()
{
lock (syncRoot)
{
long timestamp = GetTimestamp();
if (Snowflake.lastTimestamp == timestamp)
{ //同一微妙中生成ID
sequence = (sequence + 1) & sequenceMask; //用&运算计算该微秒内产生的计数是否已经到达上限
if (sequence == 0)
{
//一微妙内产生的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;
}
} }
    [TestClass]
public class SnowflakeUnitTest1
{
/// <summary>
/// 动态生产有规律的ID Snowflake算法是Twitter的工程师为实现递增而不重复的ID实现的
/// </summary>
[TestMethod]
public void SnowflakeTestMethod1()
{
var ids = new List<long>();
for (int i = 0; i < 1000000; i++)//测试同时100W有序ID
{
ids.Add(Snowflake.Instance().GetId());
}
for (int i = 0; i < ids.Count - 1; i++)
{
Assert.IsTrue(ids[i] < ids[i+1]);
}
}
}
namespace ConsoleApplicationTester
{
class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 1000; i++)
{
Console.WriteLine("开始执行 " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ffffff") + " " + Snowflake.Instance().GetId()); Console.WriteLine("Snowflake.maxMachineId:" + Snowflake.maxMachineId);
}
}
}
}

C# 实现 Snowflake算法 ID生成的更多相关文章

  1. Snowflake算法 ID生成

    Snowflake算法 ID生成 http://blog.csdn.net/w200221626/article/details/52064976 使用UUID或者GUID产生的ID没有规则 Snow ...

  2. Twitter的SnowFlake分布式id生成算法

    二进制相关知识回顾 1.所有的数据都是以二进制的形式存储在硬盘上.对于一个字节的8位到底是什么类型 计算机是如何分辨的呢? 其实计算机并不负责判断数据类型,数据类型是程序告诉计算机该如何解释内存块. ...

  3. SnowFlake --- 分布式id生成算法

    转载自:https://segmentfault.com/a/1190000011282426 概述 SnowFlake算法生成id的结果是一个64bit大小的整数,它的结构如下图: 1位,不用.二进 ...

  4. SnowFlake分布式ID生成及反解析

    概述 分布式id生成算法的有很多种,Twitter的SnowFlake就是其中经典的一种,SnowFlake算法生成id的结果是一个64bit大小的整数,它的结构如下图: 1位,不用.二进制中最高位为 ...

  5. twitter的ID生成器的snowFlake算法的自造版

    snowFlake算法在生成ID时特别高效,可参考:https://segmentfault.com/a/1190000011282426 SnowFlake算法生成id的结果是一个64bit大小的整 ...

  6. ID生成算法(一)——雪花算法

    JavaScript生成有序GUID或者UUID,这时就想到了雪花算法. 原理介绍: snowFlake算法最终生成ID的结果为一个64bit大小的整数,结构如下图: 解释: 1bit.二进制中最高位 ...

  7. 架构设计 | 分布式业务系统中,全局ID生成策略

    本文源码:GitHub·点这里 || GitEE·点这里 一.全局ID简介 在实际的开发中,几乎所有的业务场景产生的数据,都需要一个唯一ID作为核心标识,用来流程化管理.比如常见的: 订单:order ...

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

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

  9. 分布式ID生成系统 UUID与雪花(snowflake)算法

    Leaf——美团点评分布式ID生成系统 -https://tech.meituan.com/MT_Leaf.html 网游服务器中的GUID(唯一标识码)实现-基于snowflake算法-云栖社区-阿 ...

随机推荐

  1. liunx下tomcat启动 Cannot find ./catalina.sh

    执行启动tomcat命令./startup.sh 提示 Cannot find ./catalina.sh The file is absent or does not have execute pe ...

  2. 14 接口-interface的定义与实现

    接口的基本语法一: 1.使用interface 定义 2.接口当中的方法都是抽象方法 3.接口当中的方法都是public权限 接口的定义: interface USB { public void re ...

  3. 【USACO 1.2】Palindromic Squares

    进制转换,然后判断是否是回文 /******************************************* TASK: palsquare LANG: C++ Created Time: ...

  4. bzoj4402: Claris的剑

    首先,对于本质相同的构造,我们只计算字典序最小的序列 假设序列中最大的元素为top 我们很容易发现这样的序列一定是1,2,..,1,2,3,2,3,...,2,3,4,3,4.........,top ...

  5. BZOJ 4384: [POI2015]Trzy wieże

    4384: [POI2015]Trzy wieże Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 217  Solved: 61[Submit][St ...

  6. 表头不动,内容滚动的例子(纯css+html)

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  7. hbase批量数据导入报错:NotServingRegionException

    批量导入数据到hbase的时候,报错: org.apache.hadoop.hbase.client.RetriesExhaustedWithDetailsException: Failed 1 ac ...

  8. POJ3735 矩阵

    题意:有n只猫咪,开始时每只猫咪有花生0颗,现有一组操作,由下面三个中的k个操作组成:        1. g i 给i只猫咪一颗花生米        2. e i 让第i只猫咪吃掉它拥有的所有花生米 ...

  9. Uva10881 Piotr's Ants

    蚂蚁相撞会各自回头.←可以等效成对穿而过,这样移动距离就很好算了. 末状态蚂蚁的顺序和初状态其实是相同的. 那么剩下的就是记录每只蚂蚁的标号,模拟即可. /*by SilverN*/ #include ...

  10. [NOIP2015] 提高组 洛谷P2678 跳石头

    题目背景 一年一度的“跳石头”比赛又要开始了! 题目描述 这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石.组委会已经选择好了两块岩石作为比赛起点和终点.在起点和终点之间,有 N 块岩石(不 ...