为什么要分库分表

79 阅读3分钟

分库分表是互联网企业的常见技术优化手段。主要用于应对高并发、大流量的场景。

解决什么问题

分库、分表虽然总被一起提及,但分库和分表要解决的技术问题是不同的。

优化手段解决的问题
分表解决数据量大导致的B+树高度增加,查询速度下降。
分库解决数据库容量、CPU、IO资源瓶颈问题解决从库增加造成的主从延迟增加

分表

分表通常解决数据量大的问题。当单表行数超过500w后,通常就要考虑分表了。

分表后数据量下降,每个表的B+索引树高度降级。每次索引数据的速度得到提升。

image.png

分库

数据库部署在单个主机上,数据库严重依赖单机性能。

在服务发展早期,随着业务扩量,数据库的部署会经历以下过程:

  1. 业务早期时,通常选择单机部署多DB来节约成本。
  2. 随着业务发展,单机容量、CPU、IO无法支撑多DB。这时可以选择单机部署单DB,来满足业务诉求。
  3. 随着业务不断长,普通物理机的内存、磁盘、CPU不足以支撑高性能的DB。这时候可以通过升级主机配置来满足业务发展。
  4. 业务飞速发展后,主机配置已经几乎达到顶配,升级也越来越困难,单点问题越来越明显。这时就需要用到分库技术了。

image.png

当数据库分库后,单机造成的性能问题被极大改善,数据库可以承受的流量极大提高。

image.png

分库分表算法

分库分表需要选择一个分表字段来进行分表。利用分表字段可以计算出数据所在的库、表信息。

分表算法通常有以下几种:

直接取模

直接取模的方式比较简单,例如要通过userId字段将表分成128个。则数据所在的表是n%128。

一致性hash

直接取模是比较常用的分表算法,可以让数据比较均匀的分布在多张表中,但是有一个缺点:如果后续需要扩容,可能会涉及数据迁移,扩展性较差。

为了解决这个问题,可以通过一致性哈希算法来分表。

一致性哈希可以通过hash算法将key哈希到一个2^32个节点的空间中,如果后续新增一个节点,只会影响此节点和与他相临的节点。所需要迁移的数据比较少。

全局id生成

分库分表后,需要生成分布式id。在单表中,往往可以通过数据库唯一索引来限制唯一id。但做了分库分表后,唯一索引无法保证不同库表中的id不相同,可能发生主键冲突。

全局id通常作为分表的key。

在生成全局id,在设计的时候通常要遵循以下原则:

  1. 不重复
  2. 递增
  3. 路由相对均匀,不会出现严重倾斜
  4. 查询速度高

常见的路由key生成方式对比

策略不重复递增路由均匀查询速度
雪花算法满足不重复趋势递增满足路由均匀主键索引
UUID满足不重复某些版本满足趋势递增满足路由均匀字符串查询速度慢