一、基本概念
产生背景
在数据爆炸的年代,单表数据达到千万级别,甚至过亿的量,都是很常见的情景。这时候再对数据库进行操作就是非常吃力的事情了,select个半天都出不来数据,这时候业务已经难以维系。不得已,分库分表提上日程,我们的目的很简单,减小数据库的压力,缩短表的操作时间。
分表是什么
分表是指在一个或者多个数据库实例内,将一张表拆分为多张表存储。一般来说,分表是因为该表需要存储很庞大的记录数,如果将其堆积到一起,就会导致数据量过于庞大(一般 MySQL 的表是 5000 万条记录左右)引发性能瓶颈。一般分表会按照某种算法进行拆分,如交易记录,可能按年份拆分:
分库是什么
分库是指将一套数据库的设计结构,部署到多个数据库实例的节点中去,在应用的时候,按照一定的方法通过多个数据库实例节点访问数据。请注意,这里的数据库实例节点是一个逻辑概念,不是一个物理概念,什么意思呢?简单地说,一个机器节点可以部署多个数据库实例节点,也可以一个机器节点只部署一个数据库实例节点,所以机器节点不一定等于数据库节点。而机器节点是物理概念,是看得到的真实的机器;数据库节点是逻辑概念,是看不到的东西。为了更好地说明分库的概念,如下图
二、为什么要分库分表
移动互联网时代,海量的用户每天产生海量的数量,比如:
- 用户表:以支付宝用户为例,8亿;微信用户更是多大10亿。
- 订单表:比如美团外卖,每天都是几千万的订单
- 交易流水表:淘宝的历史订单总量应该是百亿,甚至是千亿级别
这些海量数据远不是一张表能Hold住的
事实上MySQL单表可以存储10亿级数据,只是这时候性能比较差,业界公认MySQL单表容量在1KW以下是最佳状态,因为这是它的BTREE索引树高在3~5之间。
既然一张表无法搞定,那么就想办法将数据放到多个地方,目前比较普遍的方案有3个:
- 分区
- 分库分表
- NoSQL/NewSQL:redis或mongo,TiDB
既然表的扩展有三种方案,那为什么要采用分库分表,而不采用另外两种呢?
下面将分别介绍
1、为什么不采取分区方案
分区技术与分表技术很类似,只是分区技术属于数据库内部的技术,对于开发者来说,它逻辑上
仍旧是一张表,开发时不需要改变 SQL 表名。将一张表切分为多个物理区块
由于仍然是同一张表,所以也根本解决不了单表的瓶颈问题
2、为什么不采取NoSQL/NewSQL方案
目前绝大部分项目对于NoSQL/NewSQL的定位还是为辅,真正的核心数据还是要基于事务的关系型数据库,一些缓存中间件只是对MySQL的补充、增强而已
3、为什么要进行分库分表
所以我们还是要对关系型数据库本身做扩展,真正做到把大表分离开,解决单表的瓶颈问题
三、分库分表常用中间件的介绍
分库分表之后,比如我们要插入一条数据,该插入到哪一张子表中呢,查询某条数据又该从哪一张子表查呢?这有很多的中间件来帮我们完成这些事情
常用的分库分表中间件:
- 阿里的TDDL,DRDS和cobar
- 开源社区的Sharding-jdbc
- 民间组织的MyCAT
- 360的Atlas
按照架构类型划分
- Client模式
- Proxy模式
Client模式
代表有阿里的TDDL,开源社区的sharding-jdbc(sharding-jdbc的3.x版本即sharding-sphere已经支持了proxy模式)。架构如下:
中间件是嵌入到我们的应用中的
Proxy模式
代表有阿里的cobar,民间组织的MyCAT。架构如下:
可以看到,中间件作为代理,替我们去与数据库进行交互
优缺点对比:
client优点:
- 实现简单,易于使用,因为中间件作为客户端库集成在应用程序中
- 天然去中心化,不需要单独部署中间件
client缺点:
- 无法跨语言。还有版本升级很困难,耦合度非常高,因为是与应用代码绑在一起的
- 对应用有一定侵入性,需要在应用代码中集成和配置中间件。
proxy优点:
- 多语言支持,对业务开发透明,应用可以像操作单个数据库一样操作分库分表
- 天然去中心化,不需要单独部署中间件
proxy缺点:
- 实现复杂,因为代理需要实现数据库通信协议
- Proxy本身需要保证高可用,否则Proxy的故障会影响整个数据库的访问。
- 需要考虑租户隔离,多个应用访问Proxy代理的底层数据库时,需要处理好资源竞争问题。