当前位置 博文首页 > 文章内容

    分布式ID

    作者: 栏目:未分类 时间:2020-07-02 14:10:35

    本站于2023年9月4日。收到“大连君*****咨询有限公司”通知
    说我们IIS7站长博客,有一篇博文用了他们的图片。
    要求我们给他们一张图片6000元。要不然法院告我们

    为避免不必要的麻烦,IIS7站长博客,全站内容图片下架、并积极应诉
    博文内容全部不再显示,请需要相关资讯的站长朋友到必应搜索。谢谢!

    另祝:版权碰瓷诈骗团伙,早日弃暗投明。

    相关新闻:借版权之名、行诈骗之实,周某因犯诈骗罪被判处有期徒刑十一年六个月

    叹!百花齐放的时代,渐行渐远!



    一、概述

    之前的项目比较小,标识ID都是基于数据库主键自增,直到因为某表数据量大,采用分表时出现ID冲突问题,后来使用UUID方式解决。然后就有意识的去了解分布式相关的知识。数据分库分表后需要有唯一ID来标识一条数据,采用传统的数据库的自增ID显然不能满足需求,会有ID冲突,所以记录下分布式ID常见的解决方案

    二、解决方案(参考:https://www.cnblogs.com/captainad/p/10954331.html

    在列举分布式ID解决方案前,先了解下我们对分布式ID的要求

    • 全局唯一性:即唯一标识
    • 趋势递增:在MySQL InnoDB引擎中使用的是聚集索引,由于多数RDBMS使用B-tree的数据结构来存储索引数据,所以尽量使用有序的主键保证写入性能。
    • 单调递增:即在某种规则上保证后面的ID大于前面的ID
    • 信息安全:如果ID是连续的,爬虫就有序可循,对我们的数据造成安全影响,尽量保证ID无规则、不规则。
    • 分布ID最好包含时间戳,有利于我们通过ID解析数据生成时间

    1、UUID方式实现分布式ID

      UUID是最先想到的方式,UUID无规则不可读而且过长

      (1)优点

      •   简单方便。
      •   通过本地生成,没有性能问题。
      •   因为具备全球唯一的特性,所以对于数据库迁移这种情况不存在问题。

      (2)缺点

      •   每次生成的ID都是无序的,而且不是全数字,且无法保证趋势递增。
      •   UUID生成的是字符串,字符串存储性能差,查询效率慢。
      •   UUID长度过长,不适用于存储,耗费数据库性能。
      •   ID无一定业务含义,可读性差。

      (3)适用场景

      •   可以用来生成如token令牌一类的场景,足够没辨识度,而且无序可读,长度足够。
      •   可以用于无纯数字要求、无序自增、无可读性要求的场景。

    2、基于数据库多实例主键自增,设置步长

      在传统的数据库自增ID的基础之上,设置step增长步长,让DB之前生成的ID趋势递增且不重复。

    从上图可以看出,水平扩展的数据库集群,有利于解决数据库单点压力的问题,同时为了ID生成特性,将自增步长按照机器数量来设置,但是,这里有个缺点就是不能再扩容了,如果再扩容,ID就没法儿生成了,步长都用光了,那如果你要解决新增机器带来的问题,你或许可以将第三台机器的ID起始生成位置设定离现在的ID比较远的位置,同时把新的步长设置进去,同时修改旧机器上ID生成的步长,但必须在ID还没有增长到新增机器设置的开始自增ID值,否则就要出现重复了。

      (1)优点

      •   解决了ID生成的单点问题,同时平衡了负载。

      (2)缺点

      •   一定确定好步长,将对后续的扩容带来困难,而且单个数据库本身的压力还是大,无法满足高并发。

      (3)适用场景

      •   数据量不大,数据库不需要扩容的场景。

    这种方案,除了难以适应大规模分布式和高并发的场景,普通的业务规模还是能够胜任的,所以这种方案还是值得积累。

    3、类雪花算法

    snowflake雪花算法是twitter公司内部分布式项目采用的ID生成算法,现在开源并流行了起来,下面是Snowflake算法的ID构成图。

    这种方案巧妙地把64位分别划分成多段,分开表示时间戳差值、机器标识和随机序列,先以此生成一个64位地二进制正整数,然后再转换成十进制进行存储。其中,1位标识符,不使用且标记为0;41位时间戳,用来存储时间戳的差值;10位机器码,可以标识1024个机器节点,如果机器分机房部署(IDC),这10位还可以拆分,比如5位表示机房ID,5位表示机器ID,这样就有32*32种组合,一般来说是足够了;最后的12位随即序列,用来记录毫秒内的计数,一个节点就能够生成4096个ID序号。所以综上所述,综合计算下来,理论上Snowflake算法方案的QPS大约为409.6w/s,性能足够强悍了,而且这种方式,能够确保集群中每个节点生成的ID都是不同的,且区间内递增。

      (1)优点

      •   每秒能够生成百万个不同的ID,性能佳。
      •   时间戳值在高位,中间是固定的机器码,自增的序列在地位,整个ID是趋势递增的。
      •   能够根据业务场景数据库节点布置灵活挑战bit位划分,灵活度高。

      (2)缺点

      •   强依赖于机器时钟,如果时钟回拨,会导致重复的ID生成,所以一般基于此的算法发现时钟回拨,都会抛异常处理,阻止ID生成,这可能导致服务不可用。

    适用场景,不过目前有好多开源的方式解决了强依赖机器时钟

      •   雪花算法有很明显的缺点就是时钟依赖,如果确保机器不存在时钟回拨情况的话,那使用这种方式生成分布式ID是可行的,当然小规模系统完全是能够使用的。

    三、使用类雪花算法封装类库