• 分布式ID生成算法——雪花算法


    一、分布式ID

    ID可以唯一标识一条记录。

    对于单体架构,我们可以使用自增ID来保证ID的唯一性。但是,在分布式系统中,简单的使用自增ID就会导致ID冲突。这也就引出了分布式ID问题。分布式ID也要求满足分布式系统的高性能、高可用、高并发的特点。

    二、雪花算法

    世界上不存在两片一样的雪花。

    雪花算法(Snowflake),是Twitter公司提出的一种分布式ID生成算法,是分布式ID问题的经典解决方案。此算法生成的是一个64bit(8字节)的ID,在Java中使用8字节的long来存放,在数据库推荐用bigint来存储。

    雪花ID结构如下所示,由1bit符号位 + 41bit时间戳 + 10bit工作机器ID + 12bit序列号组成。

    雪花ID示意图

    • 符号位:恒为0,保证生成的ID为正整数。
    • 时间戳:用于记录时间戳的毫秒数,通常选用项目上线时间作为时间戳的相对起点。41bit的时间戳可以保证69年的使用,对于普通的项目绝对是够用了。
    • 工作机器ID:10bit的机器ID可以分为两部分,机房ID + 机器ID。这两部分的长度分配没有具体要求,可以根据具体情况动态调整。
    • 序列号:用于区分在同一时间戳内,同一机器生成的ID。12bit一共可以标识4096个ID。

    从上面的介绍中,我们不难看出雪花算法可以(优点):

    • 在高并发的情况下保证分布式ID的全局唯一性。
    • 生成的ID按照时间升序排列。
    三、时钟回拨问题

    时钟回拨,就是服务器上的时间突然倒退回之前的时间,时钟回拨会导致ID不唯一的问题。出现时钟回拨的原因可能是:

    • 人为更改系统时间。
    • 有时候不同的机器上需要同步时间,可能不同的机器存在误差,也会出现时钟回拨。

    出现时钟回拨后,我们要怎么解决呢?根据回拨的时间长短的不同,可以采取不同的应对方案。

    • 如果回拨的时间较短,直接在这段时间内拒绝服务,不生成ID。
    • 如果回拨的时间较长,直接阻塞是不可取的。可以提前在机器ID或者序列号中留出拓展位置0,当出现时钟回拨时,将拓展位置1,这样也可以保证生成ID的唯一性。
    四、其他分布式ID解决方案
    • UUID:Universally Unique Identifier,通用唯一识别码。但是存在长度过长(128bit)和完全随机(无序)两个缺点。如果在数据库中作为主键,一个与业务完全无关,二是更占存储空间且无序(用于索引效率低,详情请对照B+树)。
    • Redis自增:可以利用redis的原子操作incr来实现分布式ID,但是redis作为一个内存数据库,需要考虑持久化问题。如果用RDB方式持久化,redis宕机可能会导致ID重复。若采用AOF的每修改同步策略虽然能解决重复ID问题,但重启redis的恢复时间会很长。
    • 美团leaf算法:跟雪花算法其实是一个思想,这篇博客有详细讲☞传送门
  • 相关阅读:
    适合新手拿来练习的springboot+vue前后端分离小Demo
    MySQL小白入门攻略
    Docker换国内源和简单操作
    JK405R-SOP16录音芯片ic方案的测试板使用说明以及咪头如何选择
    题目 1282: 公交汽车
    大一新生常踩的5大坑,轻则损失钱财,重则影响毕业
    《86盒应用于家居中控》——实现智能家居的灵动掌控
    作为编程的我们,针对我们的职业,初入职场要如何规划呢?
    Spring Cloud Eureka:服务注册与发现
    相似性搜索:第 3 部分--混合倒排文件索引和产品量化
  • 原文地址:https://blog.csdn.net/knock_me/article/details/127415351