完美解决方案-雪花算法ID到前端之后精度丢失问题

最近公司的一个项目组要把以前的单体应用进行为服务拆分,表的ID主键使用Mybatis plus默认 的雪花算法来生成。

快下班的时候,小伙伴跑过来找我,:“快给我看看这问题,卡这卡了小半天了!”。连拉带拽,连哄带骗的把我拉到他的电脑前面。这位小伙伴在我看来技术不算是大牛,但经验也很丰富了。他都卡了半天的问题,应该不是小问题,如果我一时半会搞不定,真的是耽误我下班了,所以我很不情愿的在他的位置坐了下来。

一、现象是这样的

下面我把异常的现象给大家描述一下,小伙伴建了一张表,表的主键是id BigINT,用来存储雪花算法生成的ID,嗯,这个没有问题!

CREATE TABLE user
(
    id BIGINT(20) NOT NULL COMMENT '主键ID',
        #其他字段省略
);

使用Long 类型对应数据库ID数据。嗯,也没有问题,雪花算法生成的就是一串数字,Long类型属于标准答案!

@Data
public class User {
    private Long id;
//其他成员变量省略

在后端下断点。看到数据响应以JSON响应给前端,正常

{
id:1297873308628307970,
//其他属性省略
}

最后,这条数据返回给前端,前端接收到之后,修改这条数据,后端再次接收回来。奇怪的问题出现了:后端重新接收回来的id变成了:12978733086283000000,不再是1297873308628307970

二、分析问题

我的第一感觉是,开发小伙伴把数据给搞混了,张冠李戴了,把XXX的对象ID放到了YYY对象的ID上。所以,就按照代码从前端到后端、从后端到前端调试跟踪了一遍。

从代码的逻辑角度上没有任何问题。这时,我有点烦躁了,真的是耽误我下班了!但开工没有回头箭,既然坐下来了就得帮他解决,不然以后这队伍怎么带?想到这我又静下心来,开始思考。

1297873308628300000 ---> 1297873308628307970

这两个数长得还挺像的,似乎是被四舍五入了。此时脑袋里面冒出一个想法,是精度丢失了么?哪里能导致精度丢失?

  • 服务端都是Long类型的id,不可能丢失
  • 前端是什么类型,JSON字符串转js对象,接收Long类型的是number

上网查了一下Number精度是16位(雪花ID是19位的),So:JS的Number数据类型导致的精度丢失。问题是找到了!
小伙伴投来敬佩的眼光,5分钟就把这问题发现了。可是发现了有什么用?得解决问题啊!

三、解决问题

开发小伙伴说:那我把所有的数据库表设计,id字段由Long类型改成String类型吧。我问他你有多少张表?他说100多张吧。

  • 100多张表还有100多个实体类需要改
  • 还有各种使用到实体类的Service层要改
  • Service等改完Controller层要改
  • 关键的是String和Long都是常用类型,他还不敢批量替换

小伙伴拿起电话打算订餐,说今晚的加班是无法避免了。我想了想说:你最好别改,String做ID查询性能会下降,我再想想!后端A到前端B出现精度丢失,要么改前端,要么改后端,要么…… 。“哎哎,你等等先别订餐,后端A到前端B你用的什么做的序列化?” 小伙伴告诉我说使用的是Jackson,这就好办了,Jackson我熟悉啊!


解决思路:后端的ID(Long) ==> Jackson(Long转String) ==> 前端使用String类型的ID,前端使用js string精度就不会丢失了。 那前端再把String类型的19位数字传回服务端的时候,可以用Long接收么?当然可以,这是Spring反序列化参数接收默认支持的行为。


最终方案就是:前端用String类型的雪花ID保持精度,后端及数据库继续使用Long(BigINT)类型不影响数据库查询执行效率。

剩下的问题就是:在Spring Boot应用中,使用Jackson进行JSON序列化的时候怎么将Long类型ID转成String响应给前端。方案如下:

@Configuration
public class JacksonConfig {

  @Bean
  @Primary
  @ConditionalOnMissingBean(ObjectMapper.class)
  public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder)
  {
    ObjectMapper objectMapper = builder.createXmlMapper(false).build();

    // 全局配置序列化返回 JSON 处理
    SimpleModule simpleModule = new SimpleModule();
    //JSON Long ==> String
    simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
    objectMapper.registerModule(simpleModule);
    return objectMapper;
  }

}

小伙伴放下电话, 再次投来敬佩眼光。“走吧,一起下班!”我和小伙伴说,小伙伴一路上一直问我你是怎么学习的?我冠冕堂皇的说了一些多想多学多问之类的话。
其实我心里在想:我是一个懒人,但我不能说。能躺着绝不坐着,能自动绝不手动,能打车绝不自己开车。第一次就把事情做对,才是省时省力做好的方法!这么多年的“懒”,决定了我需要去思考更多的“捷径”,思考“捷径”的过程是我不断进阶的诀窍!
勤奋的人是社会的生产力,而懒人是社会的创造力!

欢迎关注我的博客,里面有很多精品合集

  • 本文转载注明出处(必须带连接,不能只转文字):字母哥博客

觉得对您有帮助的话,帮我点赞、分享!您的支持是我不竭的创作动力! 。另外,笔者最近一段时间输出了如下的精品内容,期待您的关注。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,125评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,293评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,054评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,077评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,096评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,062评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,988评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,817评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,266评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,486评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,646评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,375评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,974评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,621评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,642评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,538评论 2 352