转自https://www.jianshu.com/p/7aec260ca1a2

前言

在互联网还未崛起的时代,我们的传统应用都有这样一个特点:访问量、数据量都比较小,单库单表都完全可以支撑整个业务。随着互联网的发展和用户规模的迅速扩大,对系统的要求也越来越高。因此传统的MySQL单库单表架构的性能问题就暴露出来了。而有下面几个因素会影响数据库性能:

  • 数据量
    MySQL单库数据量在5000万以内性能比较好,超过阈值后性能会随着数据量的增大而变弱。MySQL单表的数据量是500w-1000w之间性能比较好,超过1000w性能也会下降。
  • 磁盘
    因为单个服务的磁盘空间是有限制的,如果并发压力下,所有的请求都访问同一个节点,肯定会对磁盘IO造成非常大的影响。
  • 数据库连接
    数据库连接是非常稀少的资源,如果一个库里既有用户、商品、订单相关的数据,当海量用户同时操作时,数据库连接就很可能成为瓶颈。

为了提升性能,所以我们必须要解决上述几个问题,那就有必要引进分库分表。

垂直拆分 or 水平拆分?

当我们单个库太大时,我们先要看一下是因为表太多还是数据量太大,如果是表太多,则应该将部分表进行迁移(可以按业务区分),这就是所谓的垂直切分。如果是数据量太大,则需要将表拆成更多的小表,来减少单表的数据量,这就是所谓的水平拆分。

垂直拆分

  • 垂直分库
    垂直分库针对的是一个系统中的不同业务进行拆分,比如用户一个库,商品一个库,订单一个库。 一个购物网站对外提供服务时,会同时对用户、商品、订单表进行操作。没拆分之前, 全部都是落到单一的库上的,这会让数据库的单库处理能力成为瓶颈。如果垂直分库后还是将用户、商品、订单放到同一个服务器上,只是分到了不同的库,这样虽然会减少单库的压力,但是随着用户量增大,这会让整个数据库的处理能力成为瓶颈,还有单个服务器的磁盘空间、内存也会受非常大的影响。 所以我们要将其拆分到多个服务器上,这样上面的问题都解决了,以后也不会面对单机资源问题。

  • 垂直分表
    也就是“大表拆小表”,基于列字段进行的。一般是表中的字段较多,将不常用的, 数据较大,长度较长(比如text类型字段)的拆分到“扩展表“。一般是针对那种几百列的大表,也避免查询时,数据量太大造成的“跨页”问题。

水平拆分

  • 水平分表
    和垂直分表有一点类似,不过垂直分表是基于列的,而水平分表是基于全表的。水平拆分可以大大减少单表数据量,提升查询效率。
  • 水平分库分表
    将单张表的数据切分到多个服务器上去,每个服务器具有相应的库与表,只是表中数据集合不同。 水平分库分表能够有效的缓解单机和单库的性能瓶颈和压力,突破IO、连接数、硬件资源等的瓶颈。

几种常用的分库分表的策略

  • HASH取模
    假设有用户表user,将其分成3个表user0,user1,user2.路由规则是对3取模,当uid=1时,对应到的是user1,uid=2时,对应的是user2.

  • 范围分片
    从1-10000一个表,10001-20000一个表。

  • 地理位置分片
    华南区一个表,华北一个表。

  • 时间分片
    按月分片,按季度分片等等,可以做到冷热数据。

分库分表后引入的问题

  • 分布式事务问题
    如果我们做了垂直分库或者水平分库以后,就必然会涉及到跨库执行SQL的问题,这样就引发了互联网界的老大难问题-"分布式事务"。那要如何解决这个问题呢?
    1.使用分布式事务中间件 2.使用MySQL自带的针对跨库的事务一致性方案(XA),不过性能要比单库的慢10倍左右。3.能否避免掉跨库操作(比如将用户和商品放在同一个库中)

  • 跨库join的问题
    分库分表后表之间的关联操作将受到限制,我们无法join位于不同分库的表,也无法join分表粒度不同的表, 结果原本一次查询能够完成的业务,可能需要多次查询才能完成。粗略的解决方法: 全局表:基础数据,所有库都拷贝一份。 字段冗余:这样有些字段就不用join去查询了。 系统层组装:分别查询出所有,然后组装起来,较复杂。

  • 横向扩容的问题
    当我们使用HASH取模做分表的时候,针对数据量的递增,可能需要动态的增加表,此时就需要考虑因为reHash导致数据迁移的问题。

  • 结果集合并、排序的问题
    因为我们是将数据分散存储到不同的库、表里的,当我们查询指定数据列表时,数据来源于不同的子库或者子表,就必然会引发结果集合并、排序的问题。如果每次查询都需要排序、合并等操作,性能肯定会受非常大的影响。走缓存可能一条路!

使用分库分表中间件

  • Mycat
    Mycat发展到现在,适用的场景已经很丰富,而且不断有新用户给出新的创新性的方案,以下是几个典型的应用场景:
    单纯的读写分离,此时配置最为简单,支持读写分离,主从切换
    分表分库,对于超过1000万的表进行分片,最大支持1000亿的单表分片
    多租户应用,每个应用一个库,但应用程序只连接Mycat,从而不改造程序本身,实现多租户化报表系统,借助于Mycat的分表能力,处理大规模报表的统计
    替代Hbase,分析大数据作为海量数据实时查询的一种简单有效方案,比如100亿条频繁查询的记录需要在3秒内查询出来结果,除了基于主键的查询,还可能存在范围查询或其他属性查询,此时Mycat可能是最简单有效的选择.
  • Sharding-JDBC
    当当网开发的简单易用、轻量级的中间件。

此外还有淘宝的TDDL,支付宝的OneProxy,360的Atlas等。

MySQL分库分表原理的更多相关文章

  1. 高可用Mysql架构_Mysql主从复制、Mysql双主热备、Mysql双主双从、Mysql读写分离(Mycat中间件)、Mysql分库分表架构(Mycat中间件)的演变

    [Mysql主从复制]解决的问题数据分布:比如一共150台机器,分别往电信.网通.移动各放50台,这样无论在哪个网络访问都很快.其次按照地域,比如国内国外,北方南方,这样地域性访问解决了.负载均衡:M ...

  2. mysql分库分表(二)

    mysql分库分表 参考: https://www.cnblogs.com/dongruiha/p/6727783.html https://www.cnblogs.com/oldUncle/p/64 ...

  3. mysql分库分表(一)

    mysql分库分表 参考: https://blog.csdn.net/xlgen157387/article/details/53976153 https://blog.csdn.net/cleve ...

  4. Mysql分库分表方案

    Mysql分库分表方案 1.为什么要分表: 当一张表的数据达到几千万时,你查询一次所花的时间会变多,如果有联合查询的话,我想有可能会死在那儿了.分表的目的就在于此,减小数据库的负担,缩短查询时间. m ...

  5. MYSQL分库分表和不停机更改表结构

    在MYSQL分库分表中我们一般是基于数据量比较大的时间对mysql数据库一种优化的做法,下面我简单的介绍一下mysql分表与分库的简单做法. .分库分表 很明显,一个主表(也就是很重要的表,例如用户表 ...

  6. MySQL分库分表备份脚本

    MySQL分库备份脚本 #脚本详细内容 [root@db02 scripts]# cat /server/scripts/Store_backup.sh #!/bin/sh MYUSER=root M ...

  7. 【分库、分表】MySQL分库分表方案

    一.Mysql分库分表方案 1.为什么要分表: 当一张表的数据达到几千万时,你查询一次所花的时间会变多,如果有联合查询的话,我想有可能会死在那儿了.分表的目的就在于此,减小数据库的负担,缩短查询时间. ...

  8. Java互联网架构-Mysql分库分表订单生成系统实战分析

    概述 分库分表的必要性 首先我们来了解一下为什么要做分库分表.在我们的业务(web应用)中,关系型数据库本身比较容易成为系统性能瓶颈,单机存储容量.连接数.处理能力等都很有限,数据库本身的“有状态性” ...

  9. (转)企业Shell实战-MySQL分库分表备份脚本

    本文来自http://www.xuliangwei.com/xubusi/252.html 免费视频讲解见 http://edu.51cto.com/course/course_id-5064.htm ...

  10. 思考--mysql 分库分表的思考

    查询不在分库键上怎么办,扫描所有库?由于分库了,每个库扫描很快?所以比单个表的扫描肯定快,可以这样理解吗. 多表jion怎么弄,把内层表发给每个分库吗? citus,tidb 都有这些问题,citus ...

随机推荐

  1. 【git】3.5 git分支-远程分支

    资料来源 (1) https://git-scm.com/book/zh/v2/Git-%E5%88%86%E6%94%AF-%E8%BF%9C%E7%A8%8B%E5%88%86%E6%94%AF ...

  2. c#笔记(四)——switch

    ---恢复内容开始--- using UnityEngine; using System.Collections;   public class Script1 : MonoBehaviour {   ...

  3. 初始化centos环境脚本

    #! /bin/bashecho "java环境初始化开始"#功能描述: Centos8.5系统自动初始化脚本#自动配置:IP地址\Yum源\docer\docker-compos ...

  4. git log 查看修改历史

    git log 后面可以跟文件名,表示查看对应文件的修改记录 git log --pretty=oneline --format="%h:%ad:%an:%s" -5 git lo ...

  5. nginx配置根据url的参数值进行转发

    server { listen 8081; location / { set $tag ""; set $cs "/index/test/test"; prox ...

  6. redis常用命令之string&list

    redis常用操做 string key操作 string <key:value> set name johnget name list setnx <key value>se ...

  7. linux创建数据库以及数据库用户密码

    登录linux服务器成功后: 登录mysql: mysql -uroot -p 输入密码:xxxx 创建数据库: create database test 创建用户及密码: create user ' ...

  8. Linux安装两个anaconda

    安装过程 1.安装第一个Anaconda Anaconda的官方安装网址在 https://www.continuum.io/downloads/ 安装命令: bash Anaconda3-4.3.1 ...

  9. oracle常用知识随笔

    1.创建表空间及用户赋权 create tablespace spaceone datafile '/dev/spaceone'size 80mextent management localsegme ...

  10. iOS开发之时间格式化

    //返回当前时间,以GMT为准 NSDate * date = [NSDate date]; NSLog(@"%@", date); //显示当前时间距离1970-01-01 00 ...