分布式id生成方案-snowflake算法(代码片段)

码农在新加坡 码农在新加坡     2023-03-09     724

关键词:

背景

在互联网的业务系统中,涉及到各种各样的ID,这些ID需要保证全局唯一。我们称之为分布式ID,分布式ID需要满足 唯一性、趋势递增性、高可用性、高性能等特点。

snowflake算法,也叫雪花算法,是其中的一种分布式ID生成方案。是twitter公司内部分布式项目采用的ID生成算法,开源后广受国内大厂的好评,在该算法影响下各大公司相继开发出各具特色的分布式生成器。

讲解雪花算法前,我们先概述一下分布式ID有哪些生成方案。

分布式ID生成方案

分布式ID有以下几种生成方式:

UUID

算法的核心思想是结合机器的网卡、当地时间、一个随记数来生成UUID。

优点:本地生成,生成简单,性能好,没有高可用风险
缺点:长度过长,存储冗余,且无序不可读,查询效率低

数据库自增ID

使用数据库的id自增策略,如 MySQL 的 auto_increment。并且可以使用多台数据库分别设置不同步长,生成不重复ID的策略来实现高可用。

优点:数据库生成的ID绝对有序,高可用实现方式简单
缺点:需要独立部署数据库实例,成本高,有性能瓶颈

Redis生成ID

Redis的所有命令操作都是单线程的,本身提供像 incr 和 increby 这样的自增原子命令,所以能保证生成的 ID 肯定是唯一有序的。

优点:不依赖于数据库,灵活方便,且性能优于数据库;数字ID天然排序,对分页或者需要排序的结果很有帮助。
缺点:如果系统中没有Redis,还需要引入新的组件,增加系统复杂度;需要编码和配置的工作量比较大。

考虑到单节点的性能瓶颈,可以使用 Redis 集群来获取更高的吞吐量。假如一个集群中有5台 Redis。可以初始化每台 Redis 的值分别是1, 2, 3, 4, 5,然后步长都是 5。各个 Redis 生成的 ID 为:

A:1, 6, 11, 16, 21
B:2, 7, 12, 17, 22
C:3, 8, 13, 18, 23
D:4, 9, 14, 19, 24
E:5, 10, 15, 20, 25

步长和初始值一定需要事先确定。使用 Redis 集群也可以防止单点故障的问题。
另外,比较适合使用 Redis 来生成每天从0开始的流水号。比如订单号 = 日期 + 当日自增长号。可以每天在 Redis 中生成一个 Key ,使用 INCR 进行累加。

snowflake算法

雪花算法(Snowflake)是twitter公司内部分布式项目采用的ID生成算法,开源后广受国内大厂的好评,在该算法影响下各大公司相继开发出各具特色的分布式生成器。

Twitter的snowflake分布式ID的算法是目前广泛使用的分布式ID算法,尽管有很多变种,比如位数的不同,时间片大小不同、node bit数放在最后等各种变种,但是主要思想还是来自于snowflake的思想。

Twitter在2010年儿童节的时候在官方博客上介绍了snowflake算法,内部用来表示每一条tweet。

snowflake算法采用64bit存储ID, 最高位备用,暂时不使用。接下来的41 bit做时间戳,最小时间单位为毫秒。再接下来的10 bit做机器ID(worker id),然后最后12 bit在单位时间(毫秒)递增。

41 bit表示时间戳大约可以使用69年(2^41 -1), 为了尽可能的表示时间,时间戳可以从第一次部署的时候开始计算,比如2020-02-02 00:00:00, 这样69年内可以无虞。

10 bit区分机器,所以可以支持1024台机器。 你也可以把10bit分成两部分,一部分做数据中心的ID,一部分做机器的ID,比如55分的化,可以支持32个数据中心,每个数据中心最多可以支持32台机器。

12 bit自增值可以表示4096的ID,也就是说每台机器每毫秒最多产生4096个ID,这是它的最大性能。

正如前面所说,时间戳、机器ID、自增ID所占的位数可以根据你实际的情况做调整。

snowflake还有一个很好的特性就是基本保持顺序性,因为它的前几位是时间戳,可以对ID按照时间进行排序。

snowflake算法详解

golang核心代码如下:

var (
    // 可以设置成系统第一次上线的时间,单位:毫秒。占用41位,可以使用69年。
    Epoch int64 = 1288834974657

    // 实例的ID占用10位,最多支持1024个实例。
    NodeBits uint8 = 10

    // 步长占用12位,每一台实例上每一毫秒最多产生2^12=4096个不重复的数据。
    StepBits uint8 = 12
)

// 生成算法
func (n *Node) Generate() ID 

    n.mu.Lock()
    // 从设定的时间戳到现在经历的毫秒数
    now := time.Since(n.epoch).Nanoseconds() / 1000000
    //和上次记录一样,step加1,否则step重置为0
    if now == n.time 
        n.step = (n.step + 1) & n.stepMask

        if n.step == 0 
            for now <= n.time 
                now = time.Since(n.epoch).Nanoseconds() / 1000000
            
        
     else 
        n.step = 0
    

    n.time = now
    // 时间戳 41 位 | node 10位 | step 12位
    r := ID((now)<<n.timeShift |
        (n.node << n.nodeShift) |
        (n.step),
    )

    n.mu.Unlock()
    return r

具体的bit可以根据自己的需求进行调整,比如既可以是(41,10,12),也可以是(41,6,16)…

完整的golang代码repo:
snowflake github

优点:

  • 存储少, 8个字节
  • 可读性高
  • 性能好,可以中心化的产生ID,也可以独立节点生成

缺点:

  • 时间回拨会重复产生ID

时钟回拨

如果我们的场景需要解决时钟回拨的问题:

可以找2bit位作为时钟回拨位,发现有时钟回拨就将回拨位加1,达到最大位后再从0开始进行循环。
例如上图中的, 10 bit的机器号=>8 bit的机器号+2 bit的回拨位.
每次发现时钟回拨,就把回拨位+1.大于最大值(3)后重设为0.

如图所示,在同一个时间段,最多支持时钟回拨3次。
每次回拨后,时钟回拨位不同,导致最终生成的ID也不同。

<全文完>

原文地址:分布式ID生成方案-snowflake算法 (微信公众号)

欢迎关注我的微信公众号:【码农在新加坡】的微信公众号,有更多好的技术分享。

雪花算法snowflake分布式id生成原理详解,以及对解决时钟回拨问题几种方案讨论(代码片段)

...题3、等待时钟校正五、要点总结一、前言在日趋复杂的分布式系统中,数据量越来越大ÿ 查看详情

分布式id生成方案-snowflake算法(代码片段)

...各种各样的ID,这些ID需要保证全局唯一。我们称之为分布式ID,分布式ID需要满足唯一性、趋势递增性、高可用性、高性能等特点。snowflake算法,也叫雪花算法,是其中的一种分布式ID生成方案。是twitter公司内部... 查看详情

理解分布式id生成算法snowflake(代码片段)

理解分布式id生成算法SnowFlakehttps://segmentfault.com/a/1190000011282426#articleHeader2分布式id生成算法的有很多种,Twitter的SnowFlake就是其中经典的一种。概述SnowFlake算法生成id的结果是一个64bit大小的整数,它的结构如下图:图片描述1位,... 查看详情

id生成算法-雪花算法(snowflake)及代码实现(代码片段)

...、java实现结尾前言唯一ID可以标识数据的唯一性,在分布式系统中生成唯一ID的方案有很多,常见的方式大概有以下三种:依赖数据库,使用如MySQL自增列或Oracle序列等。UUID随机数snowflake雪花算法(本文将要讨论)一... 查看详情

snowflake雪花算法分布式实现全局id生成(代码片段)

snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。这种方案大致来说是一种以划分命名空间(UUID也算,由于比较常见,所以单独分析)来生成ID的一种算法,这种方案把64-bit分别划分成多段,分开来标示机器、时间... 查看详情

图解分布式id生成算法snowflake(代码片段)

分布式id生成算法的有很多种,Twitter的SnowFlake就是其中经典的一种。概述SnowFlake算法生成id的结果是一个64bit大小的整数,它的结构如下图: 1位,不用。二进制中最高位为1的都是负数,但是我们生成的id一般都使用整数,所... 查看详情

分布式id生成方案:雪花算法(源自twitter)

参考技术A雪花(snowflake)在自然界中,是极具独特美丽,又变幻莫测的东西:雪花算法的原始版本是scala版,用于生成分布式ID(纯数字,时间顺序),订单编号等。算法描述:snowflake.gomain.go测试结果:结论: 查看详情

一篇文章彻底搞懂snowflake算法及百度美团的最佳实践(代码片段)

写在前面的话一提到分布式ID自动生成方案,大家肯定都非常熟悉,并且立即能说出自家拿手的几种方案,确实,ID作为系统数据的重要标识,重要性不言而喻,而各种方案也是历经多代优化,请允许我用这个视角对分布式ID自动... 查看详情

snowflake算法(代码片段)

1、snowflake算法ID生成器介绍snowflake是twitter开源的一个分布式ID生成器 2、为什么使用snowflake(1)主键自增弊端:不是全局id,当多表合并、构建数据仓库、进行数据分析、会导致主键冲突(2)uuid或guid弊端:数据量过大(3)全局redis... 查看详情

分布式id生成器(代码片段)

...文将对snowflake算法进行讲解:  1.snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。  2.其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号,... 查看详情

分布式id理解snowflake算法的实现原理(代码片段)

...owflake算法的实现原理我上次也看了一个视频讲解:【分布式ID】键高并发分布式全局唯一ID雪花算法snowflake2.前提#Snowflake(雪花)是Twitter开源的高性能ID生成算法(服务)。上图是Snowflake的Github仓库,mas 查看详情

springboot分布式全局唯一id的生成-雪花算法snowflake

一背景描述1.1问题产生在分布式系统中,怎么使用全局唯一id?在分布式是,微服务的架构中,或者大数据分库分表中,多个不同节点怎么保持每台机器生成的主键id不重复,具有唯一性?方案1:mys... 查看详情

常见分布式id生成方案(代码片段)

文章目录一、为什么要用分布式ID1、什么是分布式ID2、那么分布式ID需要满足哪些条件二、分布式ID有哪些生成方式1、基于UUID2、基于数据库自增ID3、基于数据库集群模式4、基于数据库的号段模式5、基于Redis模式6、基于雪花算法... 查看详情

常见分布式id生成方案(代码片段)

文章目录一、为什么要用分布式ID1、什么是分布式ID2、那么分布式ID需要满足哪些条件二、分布式ID有哪些生成方式1、基于UUID2、基于数据库自增ID3、基于数据库集群模式4、基于数据库的号段模式5、基于Redis模式6、基于雪花算法... 查看详情

分布式id生成方案总结整理(代码片段)

文章目录1、为什么需要分布式ID?2、业务系统对分布式ID有什么要求?3、分布式ID生成方案3.1UUID3.2、数据库自增3.3、号段模式3.4、Redis实现3.4、雪花算法(SnowFlake)3.5、百度Uidgenerator3.6、美团Leaf3.7、滴滴TinyID1、... 查看详情

分布式系统唯一id生成方案汇总(代码片段)

目录1.数据库自增长序列或字段2.UUID3.UUID的变种4.Redis生成ID5.Twitter的snowflake(雪花)算法6.利用zookeeper生成唯一ID7.MongoDB的ObjectId8.TiDB的主键更多相关文章点点这里系统唯一ID是我们在设计一个系统的时候常常会遇见的问题,也常... 查看详情

分布式系统唯一id生成方案汇总(代码片段)

目录1.数据库自增长序列或字段2.UUID3.UUID的变种4.Redis生成ID5.Twitter的snowflake算法6.利用zookeeper生成唯一ID7.MongoDB的ObjectId8.TiDB的主键系统唯一ID是我们在设计一个系统的时候常常会遇见的问题,也常常为这个问题而纠结。生成ID... 查看详情

snowflake算法实现(代码片段)

一 背景在分布式系统中,如何在各个不同的服务器产生 ID 值?例如,有一个订单系统部署在A、B 两个节点上,那么如何在这两个节点上产生各自的订单 ID,并且保证 ID 值不会冲突。通常有三种解决方案... 查看详情