发号器:如何保证分库分表后ID的全局唯一性?
我们通过分库分表和主从读写分离的方式解决了数据库的扩展性问题,但是在,数据库在分库分表之后,我们在使用数据库时存在的许多限制,比如说查询的时候必须带着分区键;一些聚合类的查询(像是 count())性能较差,需要考虑使用计数器等其它的解决方案,其实分库分表还有一个问题,就是主键的全局唯一性的问题。
数据库的主键要如何选择?
数据库中的每一条记录都需要有一个唯一的标识,依据数据库的第二范式,数据库中每一个表中都需要有一个唯一的主键,其他数据元素和主键一一对应。
那么关于主键的选择就成为一个关键点了,一般来讲,你有两种选择方式:
- 使用业务字段作为主键,比如说对于用户表来说,可以使用手机号,email 或者身份证号作为主键。
- 使用生成的唯一 ID 作为主键。
不过对于大部分场景来说,第一种选择并不适用,比如像评论表你就很难找到一个业务字段 作为主键,因为在评论表中,你很难找到一个字段唯一标识一条评论。而对于用户表来说, 我们需要考虑的是作为主键的业务字段是否能够唯一标识一个人,一个人可以有多个 email 和手机号,一旦出现变更 email 或者手机号的情况,就需要变更所有引用的外键信息,所以使用 email 或者手机作为主键是不合适的。
因此,还是使用生成的 ID 作为数据库的主键。不单单是因为它的唯一性,更是因为一旦生成就不会变更,可以随意引用。
在单库单表的场景下,我们可以使用数据库的自增字段作为 ID,因为这样最简单,对于开发人员来说也是透明的。但是当数据库分库分表后,使用自增字段就无法保证 ID 的全局唯 一性了。
当我们分库分表之后,同一个逻辑表的数据被分布到多个库中,这时如果使用数据库自增字段作为主键,那么只能保证在这个库中是唯一的,无法保证全局的唯一性。那么 假如你来设计用户系统的时候,使用自增 ID 作为用户 ID,就可能出现两个用户有两个相同的 ID,这是不可接受的,那么要怎么做呢?还是搭建发号器服务来生成全局唯一的 ID。

本文探讨如何在分库分表的数据库架构中,通过Snowflake算法实现全局唯一的ID生成,以及如何选择主键,解决业务中评论、用户ID的唯一性问题。还介绍了Twitter和美图采用发号器服务的实践案例。
最低0.47元/天 解锁文章
1775

被折叠的 条评论
为什么被折叠?



