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. JavaEE 之 Spring Data JPA

    1.事务 a.事务的关键属性(ACID) ①原子性(atomicity):事务的原子性确保动作要么全部完成,要么完全不起作用 ②一致性(consistency):一旦所有事务动作完成,事务就被提交.也 ...

  2. POJ 3126 Prime Path【BFS】

    <题目链接> 题目大意: 给你两个四位数,它们均为素数,以第一个四位数作为起点,每次能够变换该四位数的任意一位,变换后的四位数也必须是素数,问你是否能够通过变换使得第一个四位数变成第二个四 ...

  3. python数据结构之希尔排序

    def shell_sort(alist): n=len(alist) gap= int(n / 2) #步长 while gap>0: for i in range(gap,n): j=i w ...

  4. SpringMVC(二七) 自定义视图

    可以参考博客http://www.cnblogs.com/parryyang/p/5683600.html,举例很清晰. 对自定义的视图名称匹配不同的解析器进行解析. 作用:自己定义视图,视图继承vi ...

  5. linux 学习笔记五 查看文件篇章

    1 diff -y  test.txt  test2.txt 输出源文件与目标文件的全部 分为左右两篮 如下 --------------------------------------------- ...

  6. Linux ubantu中安装虚拟/使用环境virtualenv以及python flask框架

    今天学习了python flask框架的安装过程以及使用案例,感觉网上讲的东西都没有从我们这种初学者的角度去考虑(哈哈),最后还是奉上心得: 1.安装virtualenv $ sudo apt-get ...

  7. asp.net core 依赖注入实现全过程粗略剖析(1)

    转载请注明出处: https://home.cnblogs.com/u/zhiyong-ITNote/ 常用扩展方法 注入依赖服务: new ServiceCollection().AddSingle ...

  8. XamarinSQLite教程在Xamarin.Android项目中定位数据库文件

    XamarinSQLite教程在Xamarin.Android项目中定位数据库文件 实际开发中,经常需要验证数据库操作的正确性.这个时候,需要打开数据库文件,进行确认.下面是如何找到MyDocumen ...

  9. java 日期递增

    public static void main(String[] args) throws ParseException { // 方法一 // Format f = new SimpleDateFo ...

  10. 2017-9-11-Linux开机启动脚本

    参考文章:https://www.magentonotes.com/ubuntu-config-autostart-shell-script.html 还是先开门见山的说,Linux需要添加开机启动程 ...