关于Snowflake 生成53位ID
1, bug现象: 没有经过处理的Snowflake 生成的是64位bit的唯一ID,但由于多数时候我们前台用到js,但是js只支持53位bit的数值。这样就导致了传到前台的64位的丢失精度。
解决思路:修改SnowFlake 的算法,使它生成 53bit的唯一ID,就可以了,代码如下
package com.wisdombud.product.configure.snowflake; import java.net.InetAddress;
import java.net.UnknownHostException;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.regex.Matcher;
import java.util.regex.Pattern; public class SnowflakeIdWorker { private static final Pattern PATTERN_LONG_ID = Pattern.compile("^([0-9]{15})([0-9a-f]{32})([0-9a-f]{3})$"); private static final Pattern PATTERN_HOSTNAME = Pattern.compile("^.*\\D+([0-9]+)$"); private static final long OFFSET = LocalDate.of(2000, 1, 1).atStartOfDay(ZoneId.of("Z")).toEpochSecond(); private static final long MAX_NEXT = 0b11111_11111111_111L; private static final long SHARD_ID = getServerIdAsLong(); private static long offset = 0; private static long lastEpoch = 0; public static long getNextId() {
return nextId(System.currentTimeMillis() / 1000);
} private static synchronized long nextId(long epochSecond) {
if (epochSecond < lastEpoch) {
epochSecond = lastEpoch;
}
if (lastEpoch != epochSecond) {
lastEpoch = epochSecond;
reset();
}
offset++;
long next = offset & MAX_NEXT;
if (next == 0) {
return nextId(epochSecond + 1);
}
return generateId(epochSecond, next, SHARD_ID);
} private static void reset() {
offset = 0;
} private static long generateId(long epochSecond, long next, long shardId) {
return ((epochSecond - OFFSET) << 21) | (next << 5) | shardId;
} private static long getServerIdAsLong() {
try {
String hostname = InetAddress.getLocalHost().getHostName();
Matcher matcher = PATTERN_HOSTNAME.matcher(hostname);
if (matcher.matches()) {
long n = Long.parseLong(matcher.group(1));
if (n >= 0 && n < 8) {
return n;
}
}
} catch (UnknownHostException e) { }
return 0;
}
}
参考自: https://my.oschina.net/u/2552286/blog/3115621/print
64位的Snowflake 的算法
package com.wisdombud.product.configure.snowflake; public class SnowflakeIdWorker { private final long twepoch = 1420041600000L; private final long workerIdBits = 5L; private final long datacenterIdBits = 5L; private final long maxWorkerId = -1L ^ (-1L << workerIdBits); private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); private final long sequenceBits = 12L; private final long workerIdShift = sequenceBits; private final long datacenterIdShift = sequenceBits + workerIdBits; private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; private final long sequenceMask = -1L ^ (-1L << sequenceBits); private Long workerId = 2L; private Long datacenterId = 1L; private long sequence = 0L; private long lastTimestamp = -1L; public SnowflakeIdWorker() { } public synchronized long nextId() {
long timestamp = timeGen(); if (timestamp < 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();
} public enum SnowflakeInstance {
INSTANCE(); private SnowflakeIdWorker singleton; SnowflakeInstance() {
singleton = new SnowflakeIdWorker();
} public SnowflakeIdWorker getInstance() {
return singleton;
}
} public static Long getNextId() {
return SnowflakeInstance.INSTANCE.getInstance().nextId();
}
}
关于Snowflake 生成53位ID的更多相关文章
- SnowFlake 生成全局唯一id
public class SnowFlakeUtil { private long workerId; private long datacenterId; private long sequence ...
- 高并发分布式系统中生成全局唯一Id汇总
数据在分片时,典型的是分库分表,就有一个全局ID生成的问题.单纯的生成全局ID并不是什么难题,但是生成的ID通常要满足分片的一些要求: 1 不能有单点故障. 2 以时间为序,或者ID里包含时间 ...
- 一秒可生成500万ID的分布式自增ID算法—雪花算法 (Snowflake,Delphi 版)
概述 分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的. 有些时候我们希望能使用一种 ...
- Mybatis-Plus默认主键策略导致自动生成19位长度主键id的坑
原创/朱季谦 某天检查一位离职同事写的代码,发现其对应表虽然设置了AUTO_INCREMENT自增,但页面新增功能生成的数据主键id很诡异,长度达到了19位,且不是从1开始递增的-- 我检查了一下,发 ...
- java 生成20位唯一ID,生成不会重复的20位数字----https://blog.csdn.net/weixin_36751895/article/details/70331781
java 生成20位唯一ID,生成不会重复的20位数字----https://blog.csdn.net/weixin_36751895/article/details/70331781
- excel中生成32位随机id
记录下如何在EXCEL中利用公式生成32位的随机id(无符号,只有数字和小写字母). ,,)),),"",DEC2HEX(RANDBETWEEN(,,)),),"&quo ...
- 动态生成16位不重复随机数、随机创建2位ID
/** 1. * 动态生成16位不重复随机数 * * @return */ public synchronized static String generate16() { StringBuffer ...
- 5位ID生成方案
最近在某微信技术群,有人问到如何生成5位唯一数字+字母字符串的算法,要保证生成的字符串唯一,且字符串内部也要唯一. 怎么样,这个需求是不是很简单,也有点特殊呢?简单是指需求简单,特殊是指,字符串长度要 ...
- 分布式ID系列(5)——Twitter的雪法算法Snowflake适合做分布式ID吗
介绍Snowflake算法 SnowFlake算法是国际大公司Twitter的采用的一种生成分布式自增id的策略,这个算法产生的分布式id是足够我们我们中小公司在日常里面的使用了.我也是比较推荐这一种 ...
随机推荐
- python自动化测试生成HTML报告
自动化测试结果执行完毕后,需要对测试结果进行查看,今天就来讲一讲如何生成HTML报告首先下载HTMLTestRunner.py文件,放在python安装目录的Lib文件夹下https://pan.ba ...
- 不用代码趣讲 ZooKeeper 集群
本文作者:HelloGitHub-老荀 Hi,这里是 HelloGitHub 推出的 HelloZooKeeper 系列,免费开源.有趣.入门级的 ZooKeeper 教程,面向有编程基础的新手. 项 ...
- OpenGL中的简单坐标系初看+VAO/VBO/EBO
你好,三角形 一: 关于坐标的问题 标准化设备坐标:输入的顶点数据就应该在标准化设备坐标范围里面即:x,y,z的值都在(-1-1)之间.在这个区间之外的坐标都会被丢弃. 1.1一旦顶点数据传入顶点着色 ...
- 【老孟Flutter】Flutter 2.0 重磅更新
老孟导读:昨天期待已久的 Flutter 2.0 终于发布了,Web 端终于提正了,春季期间我发布的一篇文章,其中的一个预测就是 Web 正式发布,已经实现了,还有一个预测是:2021年将是 Flut ...
- Java基础 随笔整理
Java基础随笔整理 为了方便阅读,特整理了相关的学习笔记 Java感想 操千曲而后晓声 Java入门 Java其他 Java虚拟机详解 语言入门百题 Java开发工具 · Eclipse Java语 ...
- C# 读取Word文本框中的文本、图片和表格(附VB.NET代码)
[概述] Word中可插入文本框,在文本框中可添加文本.图片.表格等内容.本篇文章通过C#程序代码介绍如何来读取文本框中的文本.图片和表格等内容.附VB.NET代码,有需要可作参考. [程序环境] 程 ...
- 腾讯云发布存储一体机TStor,打通全面上云“最后一公里”
随着云计算.大数据.人工智能等技术的发展,各行各业加速数据化转型,数据容量以前所未有的速度增长,本地存储难以适应数据的指数式增长. 另一方面,公有云因其易扩展.低成本.安全稳定的特点,逐渐被企业广泛应 ...
- java 动态规划解决上楼梯问题
问题描述: 你正在爬楼梯. 它需要n步才能达到顶峰. 每次你可以爬1或2步. 您可以通过多少不同的方式登顶? 注意:给定n将是一个正整数. Example 1: Input: 2 Output: 2 ...
- 攻防世界 reverse BABYRE
BABYRE XCTF 4th-WHCTF-2017 int __cdecl main(int argc, const char **argv, const char **envp) { char ...
- java例题_02 101~200以内的素数
1 /*2 [程序 2 输出素数] 2 题目:判断 101-200 之间有多少个素数,并输出所有素数. 3 程序分析:判断素数的方法:用一个数分别去除 2 到 sqrt(这个数),如果能被整除,则表明 ...