知识点 | 分库分表情况下全局唯一主键的一种简单实现

【引言】
大家知道,关系型数据库易成为系统瓶颈,单机存储容量、连接数、处理能力都有限。当单表的数据量 >1000W行或 >100G后,由于查询维度较多,即使添加从库读、优化索引,优化后性能仍下降严重。

此时就要考虑对其进行切分了,目的就在于减少数据库的负担,缩短查询时间。

在分库分表环境中,由于表中数据同时存在不同数据库中,单库主键值平时使用的自增长将不再适用,某分区数据库下自生成的ID无法保证全局唯一。因此需要单独设计全局主键,以避免跨库主键重复问题。

常见的主键生成策略有:UUID、创建主键ID表、Snowflake分布式自增ID算法。

今天就来讲一下最简单的创建主键ID表方法,此方法实现最为简单。

首先,在一台数据库中建立 sequence 表:
CREATE TABLE sequence (
id bigint(20) unsigned NOT NULL auto_increment,
stub char(1) NOT NULL default ‘’,
PRIMARY KEY (id),
UNIQUE KEY stub (stub)
) ENGINE=MyISAM;

stub字段设置为唯一索引,同一stub值在sequence表中只有一条记录,可以同时为多张表生成全局ID。

使用 MyISAM 存储引擎而非 InnoDB,目的是为了获取更高性能。
MyISAM使用的是表级别的锁,对表的读写是串行的,故不用担心在并发时两次读取同一个ID值。

当需要全局唯一的64位ID时,执行:

mysql> REPLACE INTO sequence (stub) VALUES ('a');
mysql> select * from sequence;
+----+------+
| id | stub |
+----+------+
|  1| a    |
+----+------+
1 row in set (0.00 sec)

注意:select last_insert_id() 必须与replace into在同一数据库连接下才能得到刚刚插入的新ID。

使用replace into代替insert into好处是避免了表行数过大,不需要另外定期清理。

此方案优点简单易实现,缺点也明显:存在单点问题,强依赖DB。

当DB异常时,整个分布式系统将因取不到最新的序号导致库不可用;配置主从可增加可用性,但当主库挂了,主从切换时,数据一致性在数据修改较为频繁的场景下难以保证;且,整体分布式的性能瓶颈也将受限于此产生主键ID序列的服务器读写性能上。

欢迎关注个人微信公众号:
知识点 | 分库分表情况下全局唯一主键的一种简单实现

上一篇:万字总结!新鲜出炉的Java面试真题集锦我给你们整理出来了


下一篇:php – Phar存档和存根文件用法