Mysql分库分表

关系型数据库本身比较容易成为系统瓶颈,单机存储容量、连接数、处理能力都有限。当单表的数据量达到1000W或100G以后,由于查询维度较多,即使添加从库、优化索引,做很多操作时性能仍下降严重。此时就要考虑对其进行切分了,切分的目的就在于减少数据库的负担,缩短查询时间。

数据库分布式核心内容无非就是数据切分(Sharding),以及切分后对数据的定位、整合。数据切分就是将数据分散存储到多个数据库中,使得单一数据库中的数据量变小,通过扩充主机的数量缓解单一数据库的性能问题,从而达到提升数据库操作性能的目的。

  • 垂直切分:纵向切分,根据业务耦合性,拆分表或库
    • 垂直分库:根据业务耦合性,将关联度低的不同表存储在不同的数据库。做法与大系统拆分为多个小系统类似,按业务分类进行独立划分。与"微服务治理"的做法相似,每个微服务使用单独的一个数据库。
    • 垂直分表:垂直分表是基于数据库中的"列"进行,某个表字段较多,可以新建一张扩展表,将不经常用或字段长度较大的字段拆分出去到扩展表中
  • 水平切分:横向切分,通过下标来分库分表
    • 水平分库:根据业务键拆分为不同库,库表结构、表名均相同,数据不同
    • 水平分表:根据业务键拆分为不同表,表结构相同,表名不同

垂直切分的优点

  • 解决业务系统层面的耦合,业务清晰
  • 与微服务的治理类似,也能对不同业务的数据进行分级管理、维护、监控、扩展等
  • 高并发场景下,垂直切分一定程度的提升IO、数据库连接数、单机硬件资源的瓶颈

垂直切分的缺点

  • 部分表无法join,只能通过接口聚合方式解决,提升了开发的复杂度
  • 分布式事务处理复杂
  • 依然存在单表数据量过大的问题(需要水平切分)

水平切分的优点

  • 不存在单库数据量过大、高并发的性能瓶颈,提升系统稳定性和负载能力
  • 应用端改造较小,不需要拆分业务模块

水平切分的缺点

  • 跨分片的事务一致性难以保证
  • 跨库的join关联查询性能较差
  • 数据多次扩展难度和维护量极大

1. 水平切分键值选取

根据数值范围:按照时间区间或ID区间来切分

  • 优点
    • 单表大小可控
    • 天然便于水平扩展,后期如果想对整个分片集群扩容时,只需要添加节点即可,无需对其他分片的数据进行迁移
    • 使用分片字段进行范围查找时,连续分片可快速定位分片进行快速查询,有效避免跨分片查询的问题。
    • 冷热数据分离,
    • 切分策略简单
  • 缺点
    • 数据量和请求量不均,热点数据成为性能瓶颈。连续分片可能存在数据热点,例如按时间字段分片,有些分片存储最近时间段内的数据,可能会被频繁的读写,而有些分片存储的历史数据,则很少被查询
    • uid必须要满足递增的特性

hash取模:采用hash取模的切分方式

  • 优点
    • 数据分片相对比较均匀,不容易出现热点和并发访问的瓶颈
  • 缺点
    • 后期分片集群扩容时,需要迁移旧的数据(使用一致性hash算法能较好的避免这个问题)
    • 容易面临跨分片查询的复杂问题。

2. 拆分带来的问题

事务一致性问题

  • 分布式事务,没有简单的方案,一般可使用"XA协议"和"两阶段提交"处理。
  • 对于那些性能要求很高,但对一致性要求不高的系统,往往不苛求系统的实时一致性,只要在允许的时间段内达到最终一致性即可,可采用事务补偿的方式

跨节点关联查询 join 问题

  • 全局表,也可看做是"数据字典表",就是系统中所有模块都可能依赖的一些表,为了避免跨库join查询,可以将这类表在每个数据库中都保存一份
  • 字段冗余:一种典型的反范式设计,利用空间换时间,为了性能而避免join查询
  • 数据组装:在系统层面,分两次查询,第一次查询的结果集中找出关联数据id,然后根据id发起第二次请求得到关联数据。最后将获得到的数据进行字段拼装。
  • ER分片:先确定表之间的关联关系,并将那些存在关联关系的表记录存放在同一个分片上

跨节点分页、排序、函数问题

  • 需要先在不同的分片节点中将数据进行排序并返回,然后将不同分片返回的结果集进行汇总和再次排序,最终返回给用户

全局主键避重问题

  • UUID:UUID是主键是最简单的方案,本地生成,性能高,没有网络耗时。但缺点也很明显,由于UUID非常长,会占用大量的存储空间;另外,作为主键建立索引和基于索引进行查询时都会存在性能问题
  • 结合数据库维护主键ID表

数据迁移、扩容问题

3. 什么时候考虑切分

能不切分尽量不要切分

不到万不得已不用轻易使用分库分表这个大招,避免"过度设计"和"过早优化"

数据量过大,正常运维影响业务访问

  • 对数据库备份,如果单表太大,备份时需要大量的磁盘IO和网络IO
  • 对一个很大的表进行DDL修改时,MySQL会锁住全表,这个时间会很长,这段时间业务不能访问此表,影响很大。
  • 大表会经常访问与更新,就更有可能出现锁等待。将数据切分,用空间换时间,变相降低访问压力

随着业务发展,需要对某些字段垂直拆分

数据量快速增长

安全性和可用性

参考博客

[数据库分库分表思路](https://www.cnblogs.com/butterfly100/p/9034281.html)

posted @ 2021-11-29 10:45  雾里看花的少年  阅读(53)  评论(0编辑  收藏  举报