积跬步至千里

雪花算法分布式Id以及其产生的前端精度损失解决方法

一. 分布式 id

特点:

1. 全局唯一性:全局没有重复的id标识。
2. 递增性:保证生成的 id 在业务中是递增的。
3. 高可用:确保在任何时候都能生成正确可用的id。
4. 高并发:在高并发环境下表现良好。

分布式id常见解决方案

1. UUID
java 中自带的算法,其能生成一串占 36 bit 的字符串,可以保证唯一性但无法实现有序递增,且业务可读性差。
2. 雪花算法
具体介绍写在下面。
3. Leaf
由美团开源的分布式id生成算法,能保证唯一性,递增性,但需要依赖关系数据库、Zookeeper 等中间件。可以参考:Leaf算法

二. 雪花算法

雪花算法是 Twitter 开发的一种分布式 id 生成算法,即 SnowFlake 算法,取意于自然界不存在两片完全一样的雪花,雪花算法生成的 id 也如雪花一样是独一无二的。

组成

雪花算法生成的 id 是一个 64 bit(位)的 long 型的数字(二进制的),下面给出结构图:
image

该生成的 id 主要由 4 部分构成:
1. 首位无效占位符:占用 1 bit ,其值始终为 0,没有意义。
2. 时间戳:占用 41 bit ,用来记录时间戳,为毫米级,即 2 的 41 次方大概为 69 年。
3. 机器编码:占用 10 bit ,其中高位 5 bit 是数据中心 ID,低位 5 bit 是工作节点 ID,最多可以容纳 1024 个节点。
4. 序列号:占用 12 bit ,用来记录同毫秒内产生的不同 id 。每个节点每毫秒从 0 开始不断累加,最多可以累加到 4095 ,一共可以产生 4096 个 id 。
SnowFlake算法在同一毫秒内最多可以生成 1024 X 4096 = 4194304 个全局唯一id。

三. 雪花算法导致前端精度丢失解决方法

原因:

前端 js 的 number 类型有最大值,即 2 的 53 次方,为9007199254740992,这是一个 16 位的十进制整数即前端精度为 16 位,后端采用雪花算法得到的 id 是 long 型(64 bit)的即精度为 19 位。这时候,前后端传值就会出现精度丢失。

解决方法:

1.把数据库 id 改为 String 类型,相当的麻烦,且性能会下降,此种方法不能使用。
2.采用注解方法,将@JsonSerialize(using = ToStringSerializer.class)加到需要的 id 字段上。例子如下:

public class ArticleVo {
    //防止后端Long类型转为前端JSON数据精度丢失
    @JsonSerialize(using = ToStringSerializer.class)
    private Long id;

    private String title;

    private String summary;
}

3.可以采用这个博主的全局配置类方法:点击这里查看

posted @ 2022-04-09 16:13  大阿张  阅读(765)  评论(0编辑  收藏  举报