高性能集群-分库分表
这是我架构设计专栏的第5篇文章。
我的架构设计专栏:https://www.nowcoder.com/creation/manager/columnDetail/0ybvLm
我的八股知识专栏:https://www.nowcoder.com/creation/manager/columnDetail/j8ZZk0
觉得有用的欢迎订阅专栏和关注我!
1.前言
读写分离分散了数据库读写操作的压力,但没有分散存储压力,当数据量达到千万甚至上亿条的时候,单台数据库服务器的存储能力会成为系统的瓶颈,主要体现在这几个方面:
- 数据量太大,读写的性能会下降,即使有索引,索引也会变得很大,性能同样会下降。
- 数据文件会变得很大,数据库备份和恢复需要耗费很长时间。数据文件越大,极端情况下丢失数据的风险越高(例如,机房火灾导致数据库主备机都发生故障)。
基于上述原因,**单个数据库服务器存储的数据量不能太大,需要控制在一定的范围内。为了满足业务数据存储的需求,就需要将存储分散到多台数据库服务器上。**今天我来介绍常见的分散存储的方法“分库分表”,其中包括“分库”和“分表”两大类。
2.什么是分库分表?
分库 就是将数据库中的数据分散到不同的数据库上,一般是业务分库。
分表 就是对单表的数据进行拆分,可以是垂直拆分,也可以是水平拆分
3.业务分库
**业务分库指的是按照业务模块将数据分散到不同的数据库服务器。**例如,一个简单的电商网站,包括用户、商品、订单三个业务模块,我们可以将用户数据、商品数据、订单数据分开放到三台不同的数据库服务器上,而不是将所有数据都放在一台数据库服务器上。
虽然业务分库能够分散存储和访问压力,但同时也带来了新的问题,接下来我进行详细分析。
- join 操作问题业务分库后,原本在同一个数据库中的表分散到不同数据库中,导致无法使用 SQL 的 join 查询。例如:“查询购买了化妆品的用户中女性用户的列表”这个功能,虽然订单数据中有用户的 ID 信息,但是用户的性别数据在用户数据库中,如果在同一个库中,简单的 join 查询就能完成;但现在数据分散在两个不同的数据库中,无法做 join 查询,只能采取先从订单数据库中查询购买了化妆品的用户 ID 列表,然后再到用户数据库中查询这批用户 ID 中的女性用户列表,这样实现就比简单的 join 查询要复杂一些。
- 事务问题原本在同一个数据库中不同的表可以在同一个事务中修改,业务分库后,表分散到不同的数据库中,无法通过事务统一修改。虽然数据库厂商提供了一些分布式事务的解决方案(例如,MySQL 的 XA),但性能实在太低,与高性能存储的目标是相违背的。例如,用户下订单的时候需要扣商品库存,如果订单数据和商品数据在同一个数据库中,我们可以使用事务来保证扣减商品库存和生成订单的操作要么都成功要么都失败,但分库后就无法使用数据库事务了,需要业务程序自己来模拟实现事务的功能。例如,先扣商品库存,扣成功后生成订单,如果因为订单数据库异常导致生成订单失败,业务程序又需要将商品库存加上;而如果因为业务程序自己异常导致生成订单失败,则商品库存就无法恢复了,需要人工通过日志等方式来手工修复库存异常。
- 成本问题业务分库同时也带来了成本的代价,本来 1 台服务器搞定的事情,现在要 3 台,如果考虑备份,那就是 2 台变成了 6 台。
4.分表
1.怎么分表?
表将不同业务数据分散存储到不同的数据库服务器,能够支撑百万甚至千万用户规模的业务,但如果业务继续发展,同一业务的单表数据也会达到单台数据库服务器的处理瓶颈。例如,淘宝的几亿用户数据,如果全部存放在一台数据库服务器的一张表中,肯定是无法满足性能要求的,此时就需要对单表数据进行拆分。
单表数据拆分有两种方式:垂直分表和水平分表。示意图如下:
单表进行切分后,是否要将切分后的多个表分
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
不想当架构师的后端开发工程师不是好码农! 此专栏用于存放我的架构设计学习笔记,内容一部分源于网上资料,一部分源于gpt和我自己的理解。建议喜欢本专栏的盆友尽早订阅。欢迎给本专栏的文章点赞、评论!