根据twitter的snowflake算法生成唯一ID
C#版本

/// <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 = 1;
private static long twepoch = 687888001020L; //唯一时间,这是一个避免重复的随机量,自行设定不要大于当前时间戳
private static long sequence = 0L;
private static int workerIdBits = 4; //机器码字节数。4个字节用来保存机器码
public static long maxWorkerId = -1L ^ -1L << workerIdBits; //最大机器ID
private static int sequenceBits = 10; //计数器字节数,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 + 1) & IdWorker.sequenceMask; //用&运算计算该微秒内产生的计数是否已经到达上限
if (IdWorker.sequence == 0)
{
//一微妙内产生的ID计数已达上限,等待下一微妙
timestamp = tillNextMillis(this.lastTimestamp);
}
}
else
{ //不同微秒生成ID
IdWorker.sequence = 0; //计数清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(1970, 1, 1, 0, 0, 0, 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();
} }

根据twitter的snowflake算法生成唯一ID的更多相关文章
- C# 根据twitter的snowflake算法生成唯一ID
C# 版算法: using System; using System.Collections.Generic; using System.Linq; using System.Text; using ...
- 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= ...
随机推荐
- 用python socket模块实现简单的文件下载
server端: # ftp server端 import socket, os, time server = socket.socket() server.bind(("localhost ...
- rank over partition by
高级函数,分组排序 over: 在什么条件之上. partition by e.deptno: 按部门编号划分(分区). order by e.sal desc: 按工资从高到低排序(使用rank() ...
- 015_sublime插件管理及所有非常有用插件
一. <1>按照这个进行Package Control的安装 https://packagecontrol.io/installation import urllib.request,os ...
- jenkins主从从服务器发布脚本执行成功但总提示失败 FATAL: Remote call on XXXX failed
主从jenkins当调用 slave 执行编译脚本后提示如下错误,找了半天怎么也没有问题,后来忽然发现slave上java的版本和master不同,一个 1.8 一个 1.10,将slave降回1.8 ...
- linux编译内核make menuconfig报错Unable to find the ncurses libraries解决办法
在 linux 编译内核时 make menuconfig 报了下面的错误. *** Unable to find the ncurses libraries or the *** required ...
- 事务ACID特性
所谓事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位.例如,银行转帐工作:从一个帐号扣款并使另一个帐号增款,这两个操作要么都执行,要么都不执行. 数据库事务必须具备 ...
- ansible学习
声明:本博客内容是根据惨绿少年内容实践随笔,地址:http://www.cnblogs.com/clsn/p/7743792.html#comment_form 1.ansible介绍 Ansible ...
- ORACLE 表空间扩展方法
ORACLE 表空间扩展方法 环境: linux系统 工具:PL/SQL DEVELOPER 第一步:查看表空间的名字及文件所在位置: select tablespace_name, file_id, ...
- Codeforces 772C 构造 数学 + dp + exgcd
首先我们能注意到两个数x, y (0 < x , y < m) 乘以倍数互相可达当且仅当gcd(x, m) == gcd(y, m) 然后我们可以发现我们让gcd(x, m)从1开始出发走 ...
- Linux性能优化之CPU优化(一)
前言 何为性能优化?个人认为,性能优化是为了提高应用程序或系统能力为目的.那么如何才能实现对应用程序的性能调优呢?这里很设计到很多的内容,包括Linux内核.CPU架构以及Linux内核对资源的分配以 ...