MySQL主键:自增id、UUID、雪花算法

视频可看: 动画讲解:为什么不能使用自增ID或者UUID做MySQL的主键,雪花算法生成的主键存在哪些问题_哔哩哔哩_bilibili

一、MySQL分布式架构中,为什么不能使用自增id作为主键

自增主键的好处:写入效率高

弊端:只适合单机数据库,不能用于分库分表的情况,会产生重复id

1. 如果基于主键范围分片(范围固定,不容易动态调整,写满一个才写下一个),压力集中在某个分片上(尾部热点),无法做到负载均衡。可以采用其他业务字段 hash 分片,能缓解压力。
2. 如果使用AUTO INCREMENT配合replace into自增 ID,那么每当插入数据时,都会占用自增锁和插入锁。
3. 在分布式系统中,每个节点都可能有自己的自增id,在合并数据的时候,可能会出现数据冲突。
4. 在实际开发中,有时需要将两张数据表合并或迁移如果某两张表中都有有增id,就会出现主键冲突。
5. 多线程写时,自增id可能会出问题。

变通方式:不使用自增主键做数据分片,而使用业务数据的用户ID做数据分片,每个用户的数据都集中在一个库,可以做到更加的内聚。


二、UUID可以用来做主键吗?存在哪些问题?

        UUID.randomUUID().toString()
        UUID随机、无序,具有非常好的全局唯一性,但不推荐做MySQL主键。从MySQL的B+树原理看,一个page写满向下一个page写,要求下一个page的数据要大于上一个page的数据,现插入一个新数据,但UUID是随机无序的,这就很有可能导致数据的移动,根页指针的调整。插入一条数据,却伴随着几次数据移动,这是不合适的。
        UUID是由32个十六进制数字和 4个连字符组成的,不太容易阅读、查询效率不高且浪费空间。UUID是随机生成的,没有任何规律和顺序可言。当插入新记录时,这可能会导致索引分裂和磁盘碎片,并影响查询性能。
        好像可以使用有序UUID,主键有序,B+树只需在后面追加记录。

三、雪花算法(SnowFlake)生成主键,请你描述雪花算法的原理,能介绍一下它有哪些优势和不足呀,该如何解决这些不足呢?

        雪花算法是一种分布式ID生成算法,用来保证在大规模分布式系统中生成全局唯一的ID,满足唯一性和有序性,避免了分布式系统环境下的ID冲突;并且生成ID的过程中无需依赖数据库等外部系统,减少了系统复杂性。
        雪花算法是完全基于时间戳的递增而生成的,可以实现分布式部署。
优点:
(1)高性能高可用:生成时不依赖于数据库,完全在内存中生成。
(2)容量大:每秒中能生成数百万的自增ID。
(3)ID自增:存入数据库中,索引效率高。
缺点:
(1)严重依赖服务器的时钟,如果发生时钟回拨,就会出现时间重复,导致生成重复ID。
(2)41bit可存储的时间跨度是69年(从1970年算起),快不够用了。——>折中方法:时间戳减去系统上线的时间 

64bit:

1bit:不使用

41bit:时间戳(从1970-01-01  8:00)

10bit-标识位:5bit数据中心id + 5bit机器号id

12bit-序列号:用来记录同毫秒内产生的不同id 


雪花算法生成 ID 冲突问题:

1. 前提条件:
  1. 服务通过集群的方式部署,其中部分机器标识位一致。
  2. 业务存在一定的并发量,没有并发量无法触发重复问题。
  3. 生成 ID 的时机:同一毫秒下的序列号一致。
2. 标识位如何定义才能不重复?

有两种方案:预分配和动态分配

(1). 预分配(静态)

应用上线前,统计当前服务的节点数,人工去申请标识位。

这种方案,没有代码开发量,在服务节点固定或者项目少可以使用,但是解决不了服务节点动态扩容性问题。

(2). 动态分配

标识位存放在 Redis、Zookeeper、MySQL 等中间件,在服务启动的时候去请求标识位,请求后标识位并将其更新为下一个可用的

通过存放标识位,延伸出一个问题:雪花算法的 ID 是 服务内唯一还是全局唯一。

以 Redis 举例,如果要做服务内唯一,存放标识位的 Redis 节点使用自己项目内的就可以;如果是全局唯一,所有使用雪花算法的应用,要用同一个 Redis 节点。

两者的区别仅是 不同的服务间是否公用 Redis。如果没有全局唯一的需求,最好使 ID 服务内唯一,因为这样可以避免单点问题。

服务的节点数超过 1024,则需要做额外的扩展;可以扩展 10 bit 标识位,或者选择开源分布式 ID 框架。

动态分配实现方案:Redis 存储一个 Hash 结构 Key,包含两个键值对:dataCenterId 和 workerId。

        雪花算法不是万能的,并不能适用于所有场景。如果 ID 要求全局唯一并且服务节点超出 1024 节点,可以选择修改算法本身的组成,即扩展标识位,或者选择开源方案:美团LEAF、百度UID。

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值