跳转到正文
宋柏成
返回

全局随机数

全局随机数

在随着数据库数据单机达到瓶颈已经无法支持的时候就会出现分库分表的场景,这个时候数据库自带的自增主键或者简单组成的随机数已经不能满足需求了,这个时候就需要使用全局唯一 ID。 一个最基本的分布式 ID 需要满足下面这些要求:

除了这些之外,一个比较好的分布式 ID 还应保证:

常见分布式 ID 设计方案

数据库号段模式

每次从数据库批量获取一部分 ID 存放在内存中,每次需要 ID 时,从内存中获取一个,当内存中的 ID 用完之后再去数据库中批量获取一批新的 ID 存入到内存中。像滴滴开源的 Tinyid 就是基于这种方式来做的。不过,TinyId 使用了双号段缓存、增加多 db 支持等方式来进一步优化。

Tinyid 项目 Github 官网 点击跳转官网查看详细内容

缓存数据库

缓存数据库的方案,比如 Redis、MongoDB 等。一般情况下,NoSQL 方案使用 Redis 多一些。我们通过 Redis 的 incr 命令即可实现对 id 原子顺序递增。为了提高可用性和并发,我们可以使用 Redis Cluster,利用集群解决缓存重启机器或者机器故障后造成的数据丢失。

UUID

UUID 是有版本的,之于我们最常见的 UUID.randomUUID() 来说,就是版本 4 的 UUID,目前有以下五种支持方式。

  1. UUID 是根据时间和节点 ID(通常是 MAC 地址)生成。
  2. UUID 是根据标识符(通常是组或用户 ID)、时间和节点 ID 生成。
  3. 版本 3 和版本 5 确定性 UUID 通过散列(hashing)名字空间(namespace)标识符和名称生成。
  4. 使用随机性或伪随机性生成。

从上面的介绍中可以看出,UUID 可以保证唯一性,因为其生成规则包括 MAC 地址、时间戳、名字空间(Namespace)、随机或伪随机数、时序等元素,计算机基于这些规则生成的 UUID 是肯定不会重复的。虽然,UUID 可以做到全局唯一性,但是,我们一般很少会使用它。比如使用 UUID 作为 MySQL 数据库主键的时候就非常不合适:数据库主键要尽量越短越好,而 UUID 的消耗的存储空间比较大(32 个字符串,128 位)。UUID 是无顺序的,InnoDB 引擎下,数据库主键的无序性会严重影响数据库性能。

Snowflake (雪花算法)

Snowflake 是 Twitter 开源的分布式 ID 生成算法。Snowflake 由 64 bit 的二进制数字组成,这 64bit 的二进制被分成了几部分,每一部分存储的数据都有特定的含义:

如果你想要使用 Snowflake 算法的话,一般不需要你自己再造轮子。有很多基于 Snowflake 算法的开源实现比如美团的 Leaf、百度的 UidGenerator,并且,Seata 还提出了“改良版雪花算法”,针对原版雪花算法进行了一定的优化改良,解决了时间回拨问题,大幅提高的 QPS。


分享这篇文章:

上一篇
锁
下一篇
Java 异常