A New Start

关于分布式ID

一、背景

    唯一 ID,每个人都不陌生,因为在很多场景下我们都会接触到,比如:

        — 用户唯一标识

        — 订单唯一标识

        — 商品唯一标示

    唯一 ID 的生成方式是有很多的,而且在不同的业务场景下,会有不同的生成需求,即没有任何一种 ID 的生成方式是最适合所有业务场景的。

    所以说,脱离业务来谈的技术,都是耍流氓。

    下文会分析一些分布式 ID 的生成方式以供参考。

二、分布式 ID —— UUID

    UUID(Universally Unique Identifier)是通用的唯一识别码,开放软件基金会(OSF)规范定义了包括网卡MAC地址、时间戳、名字空间(Namespace)、随机或伪随机数、时序等元素。利用这些元素来生成UUID。

    UUID 是由128位二进制组成,一般转换成十六进制,然后用 String 表示。

    在 java 中有个 UUID 类,在他的注释中我们看见这里有 4 种不同的UUID的生成策略:

        UUID-01.png

        ① 基于时间的; ② 基于 DCE 安全的; ③ 基于名称空间的; ④ 基于随机数的

        一般我们默认使用第四种,

    另外,我们如果想研究更多的 UUID 的算法,附上传送门:http://www.ietf.org/rfc/rfc4122.txt

        UUID-02.png

  • 优点:

    1、无序,即生成规则是无序的

    2、本地生成,性能较高

  • 缺点:

    1、无序,因为无序带来的弊端是不能生成连续的数字

    2、32 位的十六进制,只能使用 String 来存储,空间占用相对会多一点

三、分布式 ID —— 数据库主键自增

    数据库主键自增比较简单,使用其实很方便,场景也相对比较广。

    使用时只需要将字段设置为主键即可。

  • 优点:

    1、简单,方便

    2、排序和分页都很方便

  • 缺点:

    1、并发性不好,受限于数据库性能

    2、稳定性不高,受限于数据库的服务,需担心数据库宕机

    3、分库分表时会有问题,需要定制化开发区解决

    4、业务量太明显,因为是自增的数字,所以业务量很容易被研究

    所以,对于一些简单的业务场景,比如内部系统、to-B 的系统等,业务量并不高,使用数据库主键自增的方案为最佳。

四、分布式 ID —— redis

    redis 是单线程的,可以充分保证原子性

    redis 中的俩命令一用便会:Incr 和 IncrBy

  • 优点:

    1、性能比数据库好

    2、能满足自增的序列号

  • 缺点:

    1、由于是基于内存的数据库,所以有可能会存在数据丢失的情况,会导致 ID 重复

    2、稳定性需担心,因为完全依赖于 redis

五、分布式 ID —— 雪花算法(Snowflake)

    Snowflake 是 Twitter 提出来的一个算法,其目的是生成一个 64bit 的整数,如下图:

        UUID-03.png

    说明:

        1、1bit:一般是符号位,不做处理

        2、41bit:用来记录时间戳,但是最多只可以记录69年(如果这个系统能用69年,估计已经被重构好多次了)

        3、10bit:10bit用来记录机器ID,总共可以记录1024台机器,一般用前5位代表数据中心,后面5位是某个数据中心的机器ID

        4、12bit:循环位,用来对同一个毫秒之内产生不同的ID,12位可以最多记录4095个,也就是在同一个机器同一毫秒最多记录4095个,多余的需要进行等待下毫秒。

    当然,上面的说明只是一个最常规的使用说明,在我么实际使用的时候,需要根据业务来进行酌情调整,但是总长度不变(64bit),比如:

        案例一:当我们的业务服务器位于北、上、广、深四地,则可以将 10bit 的工作机器 id 调整为 3+7 模式,即 3 位(最多看标识8)用于标识机房位置,7位(最多标识128)用于标识机器 id。

        案例二:当我们的业务量没那么大的时候,则可以将最后的 12bit 的序列号再进行划分,调整为 10 + 2 模式,即 10 位(最多标识1024)用于标识序列号,2 位用于扩展。

    雪花算法生成的 ID 有点多多,满足了 long 类型的 ID、性能并不低、无序等。

    自己实现的简单的雪花算法:

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注