万恶的IEEE754规范直接让雪花算法全盘崩
万恶的IEEE_754规范 ,直接让雪花算法全盘崩
1.事情为什么发生?
事情还要从ID的架构说起,ID在架构师的要求下,我们改成了雪花算法(Snowflake)生成ID
简单的介绍一下雪花算法,SnowFlake算法生成id的结果是一个64bit大小的整数,它的结构如下图:
SnowFlake可以保证:
- 所有生成的id按时间趋势递增
- 整个分布式系统内不会产生重复id(因为有datacenterId和workerId来做区分)
这样在遇到系统扩容,分库分表,数据迁移的场景下都不会出现太大的问题
大家伙一讨论,都觉得非常合理,就决定一股脑用雪花算法生成主键ID了
例如现在这样:
527574217068392807
527574217068392808
2.问题产生
问题是我们测试发现的,测试发现有些用户查询列表会没有值,我们把测试的ID放到数据库一查询,库内无此数据
后来我们发现后端返回的数据和前端提交上来的数据是不一样的,ID不同
3.问题验证
也就是说,一个好好的数字:527183991665594368,经过浏览器一翻译,变成了527183991665594400。
我们在浏览器的devtools里面调试一下。
4.为什么
这是因为。在JavaScript中,存在两种数字。Number和BigInt。最常用的,就是number。
最大的Number,叫做Number.MAX_SAFE_INTEGER
,它的值为:
-
2^53-1 或者
-
+/- 9,007,199,254,740,991
众所周知,Java中的Long,是64位的。Js中的这个安全Integer,完全达不到Java中定义的长度。
这就是万恶的IEEE_754规范
,它在Long长度大于17位时会出现精度丢失的问题。
在最新的TypeScript3.2中,可是直接使用BigInt这个类型进行编码,或者使用long.js这种封装后的苦,但还是太麻烦了,需要编码太多,而且还可能漏掉。
使用数字类型,传输数据,实在是不太靠谱,转来转去,就物是人非了。
最好的方式,就是使用string
进行传递。哪怕以后后台ID的长度变成了128位的,也不惧怕这种转换。
5.End
这问题,明显不是后端的锅。后端传递了正确的数据到前端,能不能处理、处理的正确不正确,根本和后端一点关系都没有
能力越强,责任越大。
实事求是,严谨细致。
本文地址:https://blog.csdn.net/u013605060/article/details/110530025
上一篇: Dubbo学习笔记(三)——实现原理
下一篇: PHP设计模式—模板方法模式