关于snowflake算法生成的ID转换为JS的数字类型由于过大导致JS精度丢失的问题
JS的数字类型目前支持的最大值为:9007199254740992,一旦数字超过这个值,JS将会丢失精度,导致前后端的值出现不一致。
JAVA的Long类型的 最大值为:9223372036854775807,snowflake的算法在实现上确实没问题的,但实际运用的时候一定要避免这个潜在的深坑。
有个博友遇到这个问题的解决方案:
https://www.cnblogs.com/do-your-best/p/9443342.html
mybatis plus的解决方案:
https://mp.baomidou.com/guide/faq.html#id-worker-生成主键太长导致-js-精度丢失
snowflake算法的java实现版本参考:
import lombok.extern.slf4j.Slf4j; /**
* id构成: 42位的时间前缀 + 10位的节点标识 + 12位的sequence避免并发的数字(12位不够用时强制得到新的时间前缀)
*/
@Slf4j
public class IdWorker { /**
* 时间起始标记点,作为基准,一般取系统的最近时间
* 此处以2018-01-01为基准时间
*/
private final long epoch = 1514736000000L;
/**
* 机器标识位数
*/
private final long workerIdBits = 4L;
/**
* 毫秒内自增位
*/
private final long sequenceBits = 12L;
/**
* 机器ID最大值:16
*/
private final long maxWorkerId = -1L ^ -1L << this.workerIdBits; private final long workerIdShift = this.sequenceBits;
private final long timestampLeftShift = this.sequenceBits + this.workerIdBits;
private final long sequenceMask = -1L ^ -1L << this.sequenceBits; private final long workerId;
/**
* 并发控制
*/
private long sequence = 0L;
private long lastTimestamp = -1L; public IdWorker(long workerId) {
if (workerId > this.maxWorkerId || workerId < 0) {
throw new IllegalArgumentException(
String.format("worker Id can't be greater than %d or less than 0", this.maxWorkerId));
}
this.workerId = workerId;
} public synchronized long nextId() {
long timestamp = this.currentTimeMillis();
if (this.lastTimestamp == timestamp) {
// 如果上一个timestamp与新产生的相等,则sequence加一(0-4095循环);
// 对新的timestamp,sequence从0开始
this.sequence = this.sequence + 1 & this.sequenceMask;
if (this.sequence == 0) {
// 重新生成timestamp
timestamp = this.tilNextMillis(this.lastTimestamp);
}
} else {
this.sequence = 0;
} if (timestamp < this.lastTimestamp) {
throw new RuntimeException(
String.format("clock moved backwards.Refusing to generate id for %d milliseconds",
(this.lastTimestamp - timestamp)));
} this.lastTimestamp = timestamp;
return timestamp - this.epoch << this.timestampLeftShift | this.workerId << this.workerIdShift | this.sequence;
} /**
* 等待下一个毫秒的到来, 保证返回的毫秒数在参数lastTimestamp之后
*/
private long tilNextMillis(long lastTimestamp) {
long timestamp = this.currentTimeMillis();
while (timestamp <= lastTimestamp) {
timestamp = this.currentTimeMillis();
}
return timestamp;
} /**
* 获得系统当前毫秒数
*/
private long currentTimeMillis() {
return System.currentTimeMillis();
} public static void main(String[] args) {
System.out.println(Long.MAX_VALUE);
}
}
上面的代码是一个全局的synchronized,如果一个服务里涉及到多个表,而这些表的ID其实可以相互重复的,那么都从同一个生成器里获取nextId的话将导致锁竞争比较激烈,从而导致效率变低,解决方案有:
1、建立多个针对不同表的这个生成器
2、在方法里的入参里加入业务放/表参数,然后使用synchronized块。
关于snowflake算法生成的ID转换为JS的数字类型由于过大导致JS精度丢失的问题的更多相关文章
- 根据twitter的snowflake算法生成唯一ID
C#版本 /// <summary> /// 根据twitter的snowflake算法生成唯一ID /// snowflake算法 64 位 /// 0---0000000000 000 ...
- C# 根据twitter的snowflake算法生成唯一ID
C# 版算法: using System; using System.Collections.Generic; using System.Linq; using System.Text; using ...
- js数字位数太大导致参数精度丢失问题
最近遇到个比较奇怪的问题,js函数里传参,传一个位数比较大,打印arguments可以看到传过来的参数已经改变. 然后查了一下,发现确实是js精度丢失造成的.我的解决方法是将数字型改成字符型传输,这样 ...
- PHP使用SnowFlake算法生成唯一ID
前言:最近需要做一套CMS系统,由于功能比较单一,而且要求灵活,所以放弃了WP这样的成熟系统,自己做一套相对简单一点的.文章的详情页URL想要做成url伪静态的格式即xxx.html 其中xxx考虑过 ...
- 使用SnowFlake算法生成唯一ID
转自:https://segmentfault.com/a/1190000007769660 考虑过的方法有 直接用时间戳,或者以此衍生的一系列方法 Mysql自带的uuid 以上两种方法都可以查到就 ...
- C# 实现 Snowflake算法生成唯一性Id
参考地址:https://blog.csdn.net/w200221626/article/details/52064976 /// <summary> /// 动态生产有规律的ID // ...
- [JS] js数字位数太大导致参数精度丢失问题
http://www.cnblogs.com/littlestart/p/6023976.html
- 基于雪花算法生成分布式ID(Java版)
SnowFlake算法原理介绍 在分布式系统中会将一个业务的系统部署到多台服务器上,用户随机访问其中一台,而之所以引入分布式系统就是为了让整个系统能够承载更大的访问量.诸如订单号这些我们需要它是全局唯 ...
- 雪花算法生成分布式ID
分布式主键ID生成方案 分布式主键ID的生成方案有以下几种: 数据库自增主键 缺点: 导入旧数据时,可能会ID重复,导致导入失败 分布式架构,多个Mysql实例可能会导致ID重复 UUID 缺点: 占 ...
随机推荐
- ESP8266进阶篇
ESP8266进阶篇 20170225(应需要,继续使用此模块!!!) 说一下如何通过内网和外网来控制我的ESP8266的数据模块 1.内网控制:(要求手机直接连接在ESP8266的WIFI上面,使用 ...
- SQL 自定义存储过程报错
begin catch ), @ErrSeverity int SELECT @ErrMsg = ' SP Error: '+ERROR_MESSAGE(), @ErrSeverity = ERROR ...
- 杭电1024----Max Sum Plus Plus
/* 这题还没有理解透彻.某个dalao也不写注释.只能自己理解了... 先求为i个元素(1<=i<=M)为一个区间的最大和,保证元素个数大于等于i个,递推到M个即可 借鉴原址:http: ...
- SQL Server中变量的声明和使用方法
网址:http://blog.sina.com.cn/s/blog_63d0c97a0100qpy7.html 声明局部变量语法: DECLARE @variable_name DataType 其中 ...
- BZOJ.3227.[SDOI2008]红黑树tree(树形DP 思路)
BZOJ orz MilkyWay天天做sxt! 首先可以树形DP:\(f[i][j][0/1]\)表示\(i\)个点的子树中,黑高度为\(j\),根节点为红/黑节点的最小红节点数(最大同理). 转移 ...
- 英语口语练习系列-C23-运动
基本词汇 1. build [bɪld] v. 建立.建造 built (过去式) be built (被动语态形式)被建成 The bridge was built in 1880. 这座桥1880 ...
- LeetCode(15. 三数之和)
问题描述 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组. 注意:答案中不可以包含重复 ...
- 纯js上传文件 很好用
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name ...
- 潭州课堂25班:Ph201805201 tornado 项目 第四课 增加用户注册登录(课堂笔记)
tornado 相关说明 在 handlers 中创建个 auth.py 用来做用户登录,在这文件中创建个类,并逐步完善 在 tornado 中创建 login.html 文件,是个登录页面 {% e ...
- MySql中的约束
mysql中的约束使用和oracle使用差别不大. 1.主键约束 如同人对应身份证,主键能够唯一地标识表中的一条记录,可以结合外键来定义数据表之间的关系. 主键约束要求主键列的数据唯一,并且不允许为空 ...