C# 根据twitter的snowflake算法生成唯一ID
C# 版算法:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Demo
{ /// <summary>
/// 根据twitter的snowflake算法生成唯一ID
/// snowflake算法 64 位
/// 0---0000000000 0000000000 0000000000 0000000000 0 --- 00000 ---00000 ---000000000000
/// 第一位为未使用(实际上也可作为long的符号位),接下来的41位为毫秒级时间,然后5位datacenter标识位,5位机器ID(并不算标识符,实际是为线程标识),然后12位该毫秒内的当前毫秒内的计数,加起来刚好64位,为一个Long型。
/// 其中datacenter标识位起始是机器位,机器ID其实是线程标识,可以同一一个10位来表示不同机器
/// </summary>
public class IdWorker
{
//机器ID
private static long workerId = ;
private static long twepoch = 687888001020L; //唯一时间,这是一个避免重复的随机量,自行设定不要大于当前时间戳
private static long sequence = 0L;
private static int workerIdBits = ; //机器码字节数。4个字节用来保存机器码
public static long maxWorkerId = -1L ^ -1L << workerIdBits; //最大机器ID
private static int sequenceBits = ; //计数器字节数,10个字节用来保存计数码
private static int workerIdShift = sequenceBits; //机器码数据左移位数,就是后面计数器占用的位数
private static int timestampLeftShift = sequenceBits + workerIdBits; //时间戳左移动位数就是机器码和计数器总字节数
public static long sequenceMask = -1L ^ -1L << sequenceBits; //一微秒内可以产生计数,如果达到该值则等到下一微妙在进行生成
private long lastTimestamp = -1L; public long nextId()
{
lock (this)
{
long timestamp = timeGen();
if (this.lastTimestamp == timestamp)
{ //同一微妙中生成ID
IdWorker.sequence = (IdWorker.sequence + ) & IdWorker.sequenceMask; //用&运算计算该微秒内产生的计数是否已经到达上限
if (IdWorker.sequence == )
{
//一微妙内产生的ID计数已达上限,等待下一微妙
timestamp = tillNextMillis(this.lastTimestamp);
}
}
else
{ //不同微秒生成ID
IdWorker.sequence = ; //计数清0
}
if (timestamp < lastTimestamp)
{ //如果当前时间戳比上一次生成ID时时间戳还小,抛出异常,因为不能保证现在生成的ID之前没有生成过
throw new Exception(string.Format("Clock moved backwards. Refusing to generate id for {0} milliseconds",
this.lastTimestamp - timestamp));
}
this.lastTimestamp = timestamp; //把当前时间戳保存为最后生成ID的时间戳
long nextId = (timestamp - twepoch << timestampLeftShift) | IdWorker.workerId << IdWorker.workerIdShift | IdWorker.sequence;
return nextId;
}
} /// <summary>
/// 获取下一微秒时间戳
/// </summary>
/// <param name="lastTimestamp"></param>
/// <returns></returns>
private long tillNextMillis(long lastTimestamp)
{
long timestamp = timeGen();
while (timestamp <= lastTimestamp)
{
timestamp = timeGen();
}
return timestamp;
} /// <summary>
/// 生成当前时间戳
/// </summary>
/// <returns></returns>
private long timeGen()
{
return (long)(DateTime.UtcNow - new DateTime(, , , , , , DateTimeKind.Utc)).TotalMilliseconds;
}
}
}
Java 版算法:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component; public class IdWorker { protected static final Logger LOG = LoggerFactory.getLogger(IdWorker.class); private long workerId;
private long datacenterId;
private long sequence = 0L; private long twepoch = 1288834974657L; private long workerIdBits = 5L;
private long datacenterIdBits = 5L;
private long maxWorkerId = -1L ^ (-1L << workerIdBits);
private long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
private long sequenceBits = 12L; private long workerIdShift = sequenceBits;
private long datacenterIdShift = sequenceBits + workerIdBits;
private long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
private long sequenceMask = -1L ^ (-1L << sequenceBits); private long lastTimestamp = -1L; public IdWorker(long workerId, long datacenterId) {
// sanity check for workerId
if (workerId > maxWorkerId || workerId < 0) {
throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
}
if (datacenterId > maxDatacenterId || datacenterId < 0) {
throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
}
this.workerId = workerId;
this.datacenterId = datacenterId;
LOG.info(String.format("worker starting. timestamp left shift %d, datacenter id bits %d, worker id bits %d, sequence bits %d, workerid %d", timestampLeftShift, datacenterIdBits, workerIdBits, sequenceBits, workerId));
} public synchronized long nextId() {
long timestamp = timeGen(); if (timestamp < lastTimestamp) {
LOG.error(String.format("clock is moving backwards. Rejecting requests until %d.", lastTimestamp));
throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
} if (lastTimestamp == timestamp) {
sequence = (sequence + 1) & sequenceMask;
if (sequence == 0) {
timestamp = tilNextMillis(lastTimestamp);
}
} else {
sequence = 0L;
} lastTimestamp = timestamp; return ((timestamp - twepoch) << timestampLeftShift) | (datacenterId << datacenterIdShift) | (workerId << workerIdShift) | sequence;
} protected long tilNextMillis(long lastTimestamp) {
long timestamp = timeGen();
while (timestamp <= lastTimestamp) {
timestamp = timeGen();
}
return timestamp;
} protected long timeGen() {
return System.currentTimeMillis();
} }
留个脚印,备用!
C# 根据twitter的snowflake算法生成唯一ID的更多相关文章
- 根据twitter的snowflake算法生成唯一ID
C#版本 /// <summary> /// 根据twitter的snowflake算法生成唯一ID /// snowflake算法 64 位 /// 0---0000000000 000 ...
- PHP使用SnowFlake算法生成唯一ID
前言:最近需要做一套CMS系统,由于功能比较单一,而且要求灵活,所以放弃了WP这样的成熟系统,自己做一套相对简单一点的.文章的详情页URL想要做成url伪静态的格式即xxx.html 其中xxx考虑过 ...
- 使用SnowFlake算法生成唯一ID
转自:https://segmentfault.com/a/1190000007769660 考虑过的方法有 直接用时间戳,或者以此衍生的一系列方法 Mysql自带的uuid 以上两种方法都可以查到就 ...
- 关于snowflake算法生成的ID转换为JS的数字类型由于过大导致JS精度丢失的问题
JS的数字类型目前支持的最大值为:9007199254740992,一旦数字超过这个值,JS将会丢失精度,导致前后端的值出现不一致. JAVA的Long类型的 最大值为:922337203 ...
- C# 实现 Snowflake算法生成唯一性Id
参考地址:https://blog.csdn.net/w200221626/article/details/52064976 /// <summary> /// 动态生产有规律的ID // ...
- twitter的snowflake算法(C#版本)
转自:http://blog.csdn.net/kinwyb/article/details/50238505 使用twitter的snowflake算法生成唯一ID. 在分布式系统中,需要生成全局U ...
- 基于Twitter的Snowflake算法实现分布式高效有序ID生产黑科技(无懈可击)
参考美团文档:https://tech.meituan.com/2017/04/21/mt-leaf.html Twitter-Snowflake算法产生的背景相当简单,为了满足Twitter每秒上万 ...
- 雪花算法生成分布式ID
分布式主键ID生成方案 分布式主键ID的生成方案有以下几种: 数据库自增主键 缺点: 导入旧数据时,可能会ID重复,导致导入失败 分布式架构,多个Mysql实例可能会导致ID重复 UUID 缺点: 占 ...
- php生成唯一id/唯一标识符/唯一订单号
/** * php 生成唯一id * https://blog.csdn.net/hzqghost/article/details/18914681 */ function guid($factor= ...
随机推荐
- 零碎收集cocos知识
Configuration类 返回环境变量 local function menuCallback(tag, pSender) printInfo("selected item tag:%d ...
- 基于.net core webapi和mongodb的日志系统
开发环境vs2017,.NET Core2.1, 数据写入到mongodb.思路就是1.提供接口写入日志,2.基于接口封装类库.3.引入类库使用 源码在最后 为什么要写它 很多开源项目像nlog.lo ...
- uva1025 dp
这题说的是给了n个车站 从1号 车站到 n号车站,有m1辆车从1 开往n 有m2 辆车从n 开往1 一个人从1 车站 到达n 车站在T 时刻 要求再 车站呆的时间尽量少 dp[i][j] 表示 在 第 ...
- 理解Linux系统中的load average(图文版)
本文转自:http://heipark.iteye.com/blog/1340384 一.什么是load average? linux系统中的Load对当前CPU工作量的度量 (WikiPedia: ...
- iview使用vue-i18n实现国际化
iview官网中和网上的例子中使用的都是webpack方式,需要import js文件,但是由于项目架构比较简单,没有使用webpack,纯html和js进行交互.所以这里就直接使用js文件引用方式. ...
- bzoj2721 / P1445 [Violet]樱花
P1445 [Violet]樱花 显然$x,y>n$ 那么我们可以设$a=n!,y=a+t(t>0)$ 再对原式通分一下$a(a+t)+ax=x(a+t)$ $a^{2}+at+ax=ax ...
- ubuntu 18.04 64bit没有声音如何解决
一.背景 1.1 笔者的机器有两张声卡,使用aplay -l可以列举出来,一张是内置声卡,另一张是显卡自带的声卡,说明声卡驱动是ok的 1.2 笔者是在浏览器中播放视频无声音 二.尝试 2.1 尝试使 ...
- vue-Treeselect实现组织机构(员工)下拉树的功能
知识点:前端使用vuetree的组件库,调用后台查询组织机构,包括人员的接口 实现下拉树的功能 查考: vue-treeselect官网:https://vue-treeselect.js.org/ ...
- ImportError: cannot import name 'izip & TypeError: 'float' object cannot be interpreted as an integer
ImportError: cannot import name 'izip' 参考:https://codereview.stackexchange.com/questions/26271/impor ...
- POJ 2513 Colored Sticks(欧拉道路+字典树+并查集)
http://poj.org/problem?id=2513 题意: 给定一些木棒,木棒两端都涂上颜色,求是否能将木棒首尾相接,连成一条直线,要求不同木棒相接的一边必须是相同颜色的. 思路: 题目很明 ...