1. 碰到的问题
前端请求量大,并发高,访问速度慢,瓶颈主要表现在:
- 单表大
- 单库大
- 网络 IO 慢
- 磁盘 IO 慢
网络、磁盘 IO 优化,主要依靠硬件升级。理论上,数据库对单库、单表的大小没有限制,但是过大的单库、单表会导致更多的请求落到单机上,给 IO 造成压力。
理想情况是,通过增加机器,能不断地增加系统并发能力。当 MySQL 单表数据量达到百万级别时,我们就应该开始存储相关的知识,以应对可能的问题。
2. 数据库架构设计的三种模式
为了解决数据库的性能问题,除了使用性能更好的硬件之外,另外一个思路就是从架构方面考虑。将一个数据库切分成多个部分放到不同的数据库上,从而缓解单一数据库的性能问题。
数据库构架设计中主要有 Shared Everthting、Shared Nothing、和 Shared Disk。通常说的 Sharding,实际上指的就是 Shared Nothing,通过增加处理单元来扩展处理能力。
2.1 Shared Everthting
通常是单个主机,完全共享 CPU、Memory、IO,并行处理能力差。例如,SQL Server。
2.2 Shared Disk
各个处理单元使用私有的 CPU、Memory,共享 IO。可以通过增加节点来提高并行处理能力,直到存储接口达到瓶颈为止。例如 Oracle Rac。
2.3 Shared Nothing
各个处理单元都有自己私有的 CPU、Memory、IO。各个处理单元之间,通过协议通信,例如:Hadopp。
3. 拆分策略
3.1 垂直拆分
将关系紧密的数据聚合在一起,拆分到不同的 Server。
- 分表:基于字段。
- 分库:基于业务。
3.2 水平拆分
将同类数据,拆分到不同的 Server。
- 分表:基于某种规则(hash 等)。
- 分库:基于表结构相同,但数据集不同。
拆分后的问题
- 主键生成(唯一 ID)
- 数据的路由(分布、节点伸缩)
- 事务支持。由数据库本身,转向了应用层。
- 跨库 Join。由应用层组装。
- count、group by、order by 等聚合
在生产环境中,通常会混合垂直、水平拆分实施。将原有数据库切分为矩阵一样,可以根据需要,无限拆分。
4. Django 中的 Sharding
4.1 分表方案
Django 分表方案,主要是自定义 Model 的 db_table 属性指定 ORM 操作的表名。
下面的例子中,使用一个 Proxy 类,通过取余算法,将不同用户的数据分配到不同表中。
|
|
需要考虑的新问题:
- 分片数量改变后,如何保证一致性
- 新建数据如何选择表
- 如何同步表结构
4.2 分库方案
Django 原生支持分库,只需要在 settings.py 文件中,新增数据库配置:
|
|
有两种使用方法:
- 使用 using,代码入侵比较强。
|
|
- 使用 Database Router
第一步,编写 Database Router,指定匹配的 app_label 使用某个 DB。
需要实现 db_for_read、db_for_write、allow_relationy 以及 allow_migrate 方法。
|
|
第二步,在 settings.py 文件中配置 Database Router。
|
|
第三步,配置 Model 的 app_label
|
|