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精度丢失的问题的更多相关文章

  1. 根据twitter的snowflake算法生成唯一ID

    C#版本 /// <summary> /// 根据twitter的snowflake算法生成唯一ID /// snowflake算法 64 位 /// 0---0000000000 000 ...

  2. C# 根据twitter的snowflake算法生成唯一ID

    C# 版算法: using System; using System.Collections.Generic; using System.Linq; using System.Text; using ...

  3. js数字位数太大导致参数精度丢失问题

    最近遇到个比较奇怪的问题,js函数里传参,传一个位数比较大,打印arguments可以看到传过来的参数已经改变. 然后查了一下,发现确实是js精度丢失造成的.我的解决方法是将数字型改成字符型传输,这样 ...

  4. PHP使用SnowFlake算法生成唯一ID

    前言:最近需要做一套CMS系统,由于功能比较单一,而且要求灵活,所以放弃了WP这样的成熟系统,自己做一套相对简单一点的.文章的详情页URL想要做成url伪静态的格式即xxx.html 其中xxx考虑过 ...

  5. 使用SnowFlake算法生成唯一ID

    转自:https://segmentfault.com/a/1190000007769660 考虑过的方法有 直接用时间戳,或者以此衍生的一系列方法 Mysql自带的uuid 以上两种方法都可以查到就 ...

  6. C# 实现 Snowflake算法生成唯一性Id

    参考地址:https://blog.csdn.net/w200221626/article/details/52064976 /// <summary> /// 动态生产有规律的ID // ...

  7. [JS] js数字位数太大导致参数精度丢失问题

    http://www.cnblogs.com/littlestart/p/6023976.html

  8. 基于雪花算法生成分布式ID(Java版)

    SnowFlake算法原理介绍 在分布式系统中会将一个业务的系统部署到多台服务器上,用户随机访问其中一台,而之所以引入分布式系统就是为了让整个系统能够承载更大的访问量.诸如订单号这些我们需要它是全局唯 ...

  9. 雪花算法生成分布式ID

    分布式主键ID生成方案 分布式主键ID的生成方案有以下几种: 数据库自增主键 缺点: 导入旧数据时,可能会ID重复,导致导入失败 分布式架构,多个Mysql实例可能会导致ID重复 UUID 缺点: 占 ...

随机推荐

  1. 从小白到区块链工程师:第一阶段:Go语言的HelloWorld初始(2)

    四.写下第一段Go语言代码“Hello World” 小建议:就是文件夹路径或者文件名称不要出现中文,可能会导致一些不必要的麻烦(编译失败) 在sublime中,我们在src文件夹上面,单击右键“Ne ...

  2. Spring AOP 切面编程实战Demo项目

    为什么会有此项目?在某日,我看博客时,看到了讲面向切面编程的内容,之前也知道spring是面向切面编程的,只是自己没有写过相关的代码,于是决定自己写一个test.但是url拦截器从外部看,和AOP有相 ...

  3. JavaScript函数、闭包、原型、面向对象

    JavaScript函数.闭包.原型.面向对象 断言 单元测试框架的核心是断言方法,通常叫assert(). 该方法通常接收一个值--需要断言的值,以及一个表示该断言目的的描述. 如果该值执行的结果为 ...

  4. Cursor for loop in Oracle

    declare l_sql ); -- variable that contains a query l_c sys_refcursor; -- cursor variable(weak cursor ...

  5. Xamarin Essentials教程语音播报TextToSpeech

    Xamarin Essentials教程语音播报TextToSpeech   语音播报是一种将文本信息转化为音频信息的技术.使用该技术,开发者可以让用户不用盯着屏幕,就可以获取到信息.例如,支付宝为商 ...

  6. Centos6.5部署Rsyslog+cron+rsync备份服务器

    1.前言 rsync是一种快速且功能非常广泛的文件复制工具.它可以在本地复制,通过任何远程shell复制到/从另一个主机复制,也可以复制到/从远程rsync守护进程.它提供了大量的选项,可以控制其行为 ...

  7. 关于java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to 实体类

    由于业务逻辑的复杂,有些sql语句写法hql不支持,所以hibernate查询直接用了sql原生查询,由于数据结果根据四个表查询出来,所以无法使用方法.addEntity(XXXXXXX.class) ...

  8. 1418 抱歉 ACM 欧拉公式

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1418 思路:一看题目,明显是要求我们找规律,于是我就在草稿纸上画了很多个图像,还是没有找到规律,于是我就在 ...

  9. 【学习笔记】python2的print和python3的print()

    python2.x和3.x中的输出语句有着明显不同 2.x中的print不是个函数,输出格式如下 Python 2.7.12+ (default, Aug 4 2016, 20:04:34) [GCC ...

  10. Express基础单词

    访问请求对象(request)或(req) 响应对象(response)或(res) 中间件(middleware) http的请求方法(method) 服务器的路径(path) 路由匹配时的函数(c ...