关于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是足够我们我们中小公司在日常里面的使用了.我也是比较推荐这一种 ...
随机推荐
- 区分函数防抖&函数节流
1. 概念区分 函数防抖:触发事件后,在n秒内函数只能执行一次,如果触发事件后在n秒内又触发了事件,则会重新计算函数延执行时间. 简单说: 频繁触发, 但只在特定的时间内才执行一次代码,如果特定时间内 ...
- 微信小程序弹出层
1.消息提示 wx.showToast wx.showToast({ title: '成功', icon: 'success', duration: 2000 })2.模态弹窗 wx.show ...
- POJ-3281(最大流+EK算法)
Dining POJ-3281 这道题目其实也是网络流中求解最大流的一道模板题. 只要建模出来以后直接套用模板就行了.这里的建模还需要考虑题目的要求:一种食物只能给一只牛. 所以这里可以将牛拆成两个点 ...
- MySql数据库列表数据分页查询、全文检索API零代码实现
数据条件查询和分页 前面文档主要介绍了元数据配置,包括表单定义和表关系管理,以及表单数据的录入,本文主要介绍数据查询和分页在crudapi中的实现. 概要 数据查询API 数据查询主要是指按照输入条件 ...
- 漏洞复现-CVE-2014-3120-ElasticSearch 命令执行漏洞
0x00 实验环境 攻击机:Win 10 靶机也可作为攻击机:Ubuntu18 (docker搭建的vulhub靶场) 0x01 影响版本 < ElasticSearch 1.2的版本 ...
- httpPost的两种方式
1,post-Body流和post参数,以下客户端代码和服务端代码可共用 客户端代码 /** * post 方法 * 抛送给EDI * @param url http://127.0.0.1:9003 ...
- Python爬虫学习三------requests+BeautifulSoup爬取简单网页
第一次第一次用MarkDown来写博客,先试试效果吧! 昨天2018俄罗斯世界杯拉开了大幕,作为一个伪球迷,当然也得为世界杯做出一点贡献啦. 于是今天就编写了一个爬虫程序将腾讯新闻下世界杯专题的相关新 ...
- 在 .NET 中使用 Flurl 高效处理Http请求
简介 官方介绍,Flurl是一个现代的,流利的,支持异步的,可测试的,可移植的,URL增强和Http客户端组件. Url构建 现在有一个登录的接口,地址如下: https://www.some-api ...
- vue 折线柱状图
需求:折线柱状图实现,显示不同提示,颜色,标记等等. 图例: 实现: <template> <div class="transaction-barline"> ...
- UI透明欺诈
判断是否存在的代码: private static boolean c(Activity paramActivity) { List localList = ((ActivityMan ...