用绝对通俗易懂的大白话来说明白 雪花算法SnowFlake

使用雪花算法的背景:

        现在很多的服务都是分布式、微服务形式的,而且业务数据里大的话,在数据库层面也可能会采取分库分表的方案。那分库分表需要面对的第一个问题就是,你分库分表后,怎么保证表中主键 id 的全局唯一性?

        对于 MySQL 而言,在分库分表之前,一个表中的主键 id 一般使用自增的方式。但是如果进行水平分表之后,多个表中肯定会生成重复的 id 值。那么如何保证水平分表后的多张表中的 id 是全局唯一性的呢?

        如果还是借助数据库主键自增的形式,那么可以让不同表初始化一个不同的初始值,然后按指定的步长进行自增。例如有3张拆分表,初始主键值为1,2,3,自增步长为3。当然也有人使用 UUID 来作为主键,但是 UUID 生成的是一个无序的字符串,MySQL 推荐使用增长的数值类型值作为主键,所以这种不适合。也可以使用 Redis 的自增原子性来生成唯一 id,但是这种方式业内比较少用。

        当然还有其他解决方案,不同互联网公司也有自己内部的实现方案。雪花算法是其中一个用于解决分布式 id 的高效方案,也是许多互联网公司在推荐使用的。

下面详细来说一下我对雪花算法的理解和记录

SnowFlake 雪花算法

        SnowFlake 中文意思为雪花,故称为雪花算法。最早是 Twitter 公司在其内部用于分布式环境下生成唯一 ID,在2014年开源 scala 语言版本。

先看一下结构图

        如上图所示,雪花算法的原理就是生成一个的 64 比特位的 long 类型的唯一 id。如果对二进制的知识稍微有所理解的话,会很容易理解的

  • 最高 1 位固定值 0,因为生成的 id 是正整数,如果是 1 就是负数了。
  • 接下来 41 位存储毫秒级时间戳,2^41/(1000*60*60*24*365)=69,大概可以使用 69 年。这个存的毫秒值不是当前的时间的毫秒值,而是从这个机器上线以来的时间的毫秒值,也就是当前毫秒值 减去 机器上线时间的毫秒值,最后得出一个毫秒值
  • 再接下 10 位存储机器码,包括 5 位 datacenterId 和 5 位 workerId。最多可以部署 2^10=1024 台机器。
  • 最后 12 位存储序列号。同一毫秒时间戳时,通过这个递增的序列号来区分。即对于同一台机器而言,同一毫秒时间戳下,可以生成 2^12=4096 个不重复 id,按秒算的话,就是一秒能生成4096000,400万个。一秒400多万,对于99.99%的公司和业务场景肯定够用了可以将雪花算法作为一个单独的服务进行部署,然后需要全局唯一 id 的系统,请求雪花算法服务获取 id 即可。

对于每一个雪花算法服务,需要先指定 10 位的机器码,这个根据自身业务进行设定即可。

例如机房号+机器号,机器号+服务号,或者是其他可区别标识的 10 位比特位的整数值都行

算法优缺点

雪花算法有以下几个优点

  • 高并发分布式环境下生成不重复 id,每秒可生成四百多万个不重复 id。
  • 基于毫秒时间戳,以及同一毫秒时间戳下序列号自增,基本保证 id 有序递增。
  • 不依赖第三方库或者中间件。
  • 算法简单,在内存中进行,效率高。

雪花算法也有缺点

  • 依赖服务器时间,服务器时钟回拨时可能会生成重复 id。算法中可通过记录最后一个生成 id 时的时间戳来解决,每次生成 id 之前比较当前服务器时钟是否被回拨,避免生成重复 id。

注意事项        

        其实雪花算法每一部分占用的比特位数量并不是固定死的。例如你的业务可能达不到 69 年之久,并且你的雪花算法服务需要部署的节点超过1024台, 那么你可以减少时间戳占用的位数,补充给机器码用。

        雪花算法中 41 位比特位不是直接用来存储当前服务器毫秒时间戳的,而是需要当前服务器时间戳减去某一个初始时间戳值,一般可以使用服务上线时间作为初始时间戳值,这个上边已经说过了。

        对于机器码,可根据自身情况做调整,例如机房号,服务器号,业务号,机器 IP 等都是可使用的。对于部署的不同雪花算法服务中,最后计算出来的机器码能区分开来即可。

        ok,到这里雪花算法的内容就讲完了,希望对你有帮助。

        后边有时间的话,我会继续讲一下 shardingSphere 分库分表的内容

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

曹举的个人博客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值