关于分库分表

1.背景

数据库在使用过程中通常会受到网络资源, CPU, 内存,磁盘等资源的制约。在以上资源确定的前提下,如果上层系统对数据库的使用诉求超出了它的承载能力,比如并发量太高,存储的数据量太大。那么就会导致请求超时、系统响应慢或者数据存储能力不足等问题。

2.方法

为了解决如上问题就需要考虑数据库的扩展,或者表的拆分,期望通过这些方式来降低数据库的负载,提升系统的处理能力。通常的处理方式包括两种,分别是主从复制,分库分表。

3.作用

以上讲述的方法分别解决的问题也是不同的。主从复制解决读多写少,单机读取压力大的问题。分库分表则是解决单机并发大引起的写入能力不足、数据存储量大造成的查询性能低下的问题。本文只讨论分库分表相关问题。

分库分表

  • 通过数据库资源的横向扩展,提升系统对外的整体处理能力、存储能力

  • 降低单表数据量,提升单表查询性能

  • 分散请求,降低单机请求负载

4.方式

分库分表方式总体上分为垂直拆分和水平拆分。垂直拆分包括 垂直分表,垂直分库;水平拆分包括水平分表,水平分库分表;通常的拆分顺序是先垂直分表,再垂直分库,然后水平分表,最后水平分库分表。因为从拆分的难道,以及拆分后系统的复杂度,运维的复杂度来讲,其程度是逐渐递增的。系统复杂度从中间件的引入,分布式事务的处理等方面产生影响;运维复杂度则是从中间件的维护成本上带来影响。几种方式体现了AKF 扩展立方体(《架构即未来》提出,这里不再单独介绍)Y轴扩展(按服务,功能拆分)和Z轴扩展(数据分区)。

AKF扩展立方体

垂直拆分:

1.垂直分表

即大表拆小表,体现在单表字段数太多,或者冗余字段数太多的情况。将使用不频繁,数据冗余,字段长度太长(如text类型)的字段拆到扩展表里面。


垂直分表

优点:通过冗余字段和其余字段数量上的减少降低单表的存储占用

缺点:业务处理会存在多次查询或者Join 查询的问题

2.垂直分库

就是将一个库内的表拆分到多个数据库,包括物理拆分和逻辑拆分。物理拆分是拆分到不同机器上,逻辑拆分是分到不同Schema(此种方式不能解决资源限制引起的问题,因此不纳入垂直分库考虑的范围。通常指的垂直分库是指第一种方式)。常用的拆分方式是根据业务模块做拆分,比如用户相关的表拆到用户库,订单相关的表拆到订单库,商品相关的表分到商品库。


垂直分库

为什么这样拆分?

可以想象一下如下场景:一个电商系统,如果订单量激增,那么原本除了需要存储订单,还需存储用户、商品、库存的数据库,就无法存储订单外的数据了,没准订单都存不了,怎么办。 如果下单相关的并发量太大,那么用户、商品、库存相关的请求就无法正常处理,同理也可能订单相关的请求也无法处理,怎么办。通过垂直分库就能解决如上问题

优点:通过资源横向扩展,提升整体存储能力,通过请求分散提升系统整体处理能力

缺点:出现分布式事务问题

水平拆分:

1.水平分表

针对数据量很大的表(如订单表),进行单表横向扩展。通常的方式有范围分片(Range), 哈希分片(Hash),时间分片。


水平分表

优点:解决单表数据量大导致的查询性能低的问题

缺点:不能解决单表数据量大导致的单机存储空间不足的问题

2.水平分库分表

针对数据量大的表进行水平拆分的同时,将表拆分到不同的物理库。

水平分库分表

优点:解决单表数据量大,单机存储不足的问题;并分散请求,解决单机负载高的问题

缺点:单表数据分散到不同数据库,导致数据分散。查询,统计,排序,Join 处理的复杂度增大

分片规则

1.范围分片(Range)

按照ID 的范围进行分片,比如 ID 1 ~ 5000 一个库,ID 5001 ~ 10000 一个库


范围分片

优点:天然分片,扩展不需要数据迁移

缺点:数据集中,易引起单机负载过大的问题

2.哈希分片(Hash)

先将分片字段Hash ,然后再根据机器数量取模进行分片

哈希分片

优点:数据分散均匀

缺点:不易扩展,扩展需要迁移数据(使用一致性Hash 算法可解决此问题)

3.时间分片

根据时间做分片,比如分成某一年1 ~ 3月,某一年4 ~ 6月两个分片

时间分片

优点:天然分片,易扩展,也方便做历史数据迁移。适合订单这类跟时间顺序关联强的数据。

缺点:数据集中,易引起单机负载过大的问题。并且单库数据量无法准确确定。

5.场景

垂直拆分

  1. 垂直分库在传统的单体系统中,当数据库在并发出现瓶颈,单库存储资源不足等情况下比较适用

  2. 垂直分表在传统的单体系统、现在的微服务架构系统,中台架构系统里。当表设计不合理(字段过多,冗余字段太多,存在长度太长字段)的情况下适用

水平拆分

  1. 水平分表在传统单体系统、现在微服务架构系统、中台架构系统中,出现单表数据量太大,单机数据存储不足,单机请求负载太大的情况下适用。但通常作为主库数据来讲,数据量大和请求量大是成正比的。因此这种场景通常不在考虑范围内。

  2. 水平分库分表在传统的单体系统中,如今的微服务架构或者中台架构场景中。当单机并发量大,单表数据量大,单机存储资源不足的情况下适用

6.现状

垂直分表对于现如今的微服务架构或者中台架构来讲。数据库本身已经根据业务模块进行了拆分,所以需要考虑垂直分库的场景很少;数据库表在设计之初已经考虑表字段的个数多,冗余字段多,长度太长字段的问题,并进行了处理,所以需要垂直分表的场景也很少。

至于水平分表,如上面场景所分析,需要考虑的场景也是很少。

反观现如今系统出现的并发量大,存储资源不足,数据量大等问题。水平分库分表才是亟待解决的问题,如下着重分析一下水平分库分表。

7.什么场景下做分库分表

分库分表是通过分库解决了单机存储限制的问题,以及通过分散请求解决了单机请求压力大的问题。然而分表为分库扩展单机存储能力提供了条件的同时,分表最重要的解决了单表数据量太大的问题。

那么单表数据量大会带来什么问题呢?

对于 MySQL 来讲通常存储用的是InnoDB作为存储引擎。那么它的查询效率受索引B+ 树数据结构的影响。对于众多数据结构来讲,B+树从算法的层面讲被DB来使用是无可挑剔的。通过控制树的高度,减少IO 操作次数来提升查询的效率。但话说回来,算法的优势不在本文讨论的范围内。对于使用B+树作为索引的InnoDB 来讲,查询效率还受Buffer Size的影响。Buffer Size 受内存资源的影响。内存不足的情况下,如果数据量太大就会造成磁盘检索次数增多,造成IO操作变多,那么查询效率就低了。

那么数据量达多大需要进行分库分表?

从行业经验来讲通常对于MySQL数据量达500W或者存储达2G 的表,或者未来三年会达到这个量级的表就需要做分库分表。当然这也是行业跟常用的系统资源做出的一个初略判断准则。具体量级受系统资源限制。不过这个准则可以作为我们系统架构的一个判断标准,为系统的未来业务承载量做好准备

8.举例

本文以电商领域比较常见的订单(Order)场景分析。

8.1 分片规则:

订单在电商领域通常数据量是很大的。并且有个特性是通常会以时间维度检索近段时间内的数据。那么采用时间分片的策略对表进行分库分库。

8.2 中间件选择:

8.2.1 中间件介绍

1. Sharing - JDBC 是当当开源的轻量级的分库分表中间件,在Java 的JDBC 层提供额外服务

Sharing - JDBC架构图

优点:轻量级,无须单独部署服务,不存在单点问题

缺点: 应用感知分库分表,对代码有侵入性

2. MyCat 是一个实现了MySQL协议的分库分表数据库代理中间件

MyCat架构图

优点:分库分表对应用透明,对业务无侵入性

缺点: 存在单点问题,需要考虑高可用架构;多一层增大网络开销

8.2.2 选择结果:

本着中间件尽量不对代码造成侵入,让应用对分库分表无感知的原则。这里选择MyCat作为分库分表中间件。

以日期为分片规则,MyCat 为中间件。对订单分库分表部署架构图

8.3 问题

随着数据库的分库分表,一些问题也随之而来,常见的问题有如下几种

  1. 分布式全局唯一ID

    数据拆分后,原有的数据库自增主键已无法保证自增主键的全局唯一性,因此MyCat 提供了全局唯一ID生成机制。全局唯一ID 生成的方式如下:

    • 本地文件方式:此方式 MyCat 将 sequence 配置到文件中,当使用到 sequence 中的配置后,MyCat 会更新classpath 中 sequence_conf.properties 文件里 sequence 的当前值。(不推荐)

      优点:本地加载,读取速度较快。

      缺点:当 MyCat 重新发布后,配置文件中的 sequence 会恢复到初始值。

    • 数据库方式:在数据库中建立一张表,存放 sequence 名称(name),sequence 当前值(current_value),步长(increment 是int 类型,表示每次读取多少个 sequence,假设为 K)等信息;

      优点:能够持久化序列号

      缺点:依赖数据库,数据库的稳定性影响生成序列号生成。如果读取序列号之后,MyCat 服务重启了,会造成序列号不连续

    • 本地时间戳: 64 位二进制 (42(毫秒)+5(机器 ID)+5(业务编码)+12(重复累加) 类似雪花算法

      优点:不需要依赖外部系统,能支持高并发高场景ID 的生成

      缺点:高可用时需要同步全局时钟,否则可能因为时间回溯导致ID重复

  2. 分布式事务

    数据拆分后会面临分布式事务问题,因此需要分布式的处理方案。

    • MyCat支持XA分布式事务(配合MySQL 版本5.7及以上)
  3. 跨库Join

    Join 是关系型数据库中最常用的一个特性,然而在分布式环境中, 跨分片的 Join 却是最复杂的,最难解决的一 个问题。因此建议能不用Join尽量不用。同时MyCat 也提供了几种Join处理方案

    • 全局表:业务系统中通常存在一些字典表。这些字典表存在变动频率低,数据量小(不超过10万)等特点。MyCat 将这些表定义为全局表。将字典表或者符合字典表特性的一些表定义为全局表。通过此方式,很好的解决了数据 Join 的难题。以全局表 + 基于 E-R 关系的分片策略,MyCat可以满足 80%以上的企业应用开发。

    • ER Join:MyCat 借鉴了 NewSQL 领域的新秀 Foundation DB 的设计思路,其将子表的存储位置依赖于主表,并且物理上紧邻存放,因此彻底解决了 Join 的效率和性能问题,根据这一思路,提出了基于 E-R 关系的数据分片策略,子表的记录与所关联的父表记录存放在同一个数据分片上。例如订单作为父表,订单明细作为子表。存储明细时讲数据存到对应订单主表的分片上。

    • Share Join:Share Join 是一个简单的跨分片 Join。目前支持 2 个表的 Join, 原理就是解析 SQL 语句,拆分成单表的 SQL 语句执行,然后把各个节点的数据汇集。

    • Spark/Storm 对 Join 扩展: MyCat 后续的功能会引入 Spark 和 Storm 来做跨分片的 join。大致流程是这样的: MyCat 调用 Spark, Storm的 API, 先把数据传送到 Spark, Storm中; 然后在 Spark, Storm 里面进行 Join; 之后把数据传回 MyCat ; 最后MyCat 再返回给客户端。

  4. 跨库 分页、group by、order by、sum、count、max

    MyCat 支持数据的多片自动路由与聚合,支持sum, count, max等常用的聚合函数, 支持跨库分页

  • 分页: 对于limit n,limit m,n 查询均有处理方案。对limit n 的形式 MyCat 会返回最先回复结果的分片数据,这样可能会引起每次返回的结果不一样。因此这种查询需要加上排序。 对于limit m,n,MyCat会改写sql ,在每个节点执行limit m+n ,再在MyCat 内部做最小堆运算。这种情况下需要开启非堆内存,否则很容易造成OOM。

  • group by、order by、sum、count、max:均会在每个分片内执行,然后在Mycat 内部进行处理

9. 结语

追本溯源分库分表是一项实现难度高,维护成本大的技术。它的设计初衷是为了解决大型系统数据库遇到的瓶颈问题。不到万不得已不要轻易使用。
任何技术选型都不能脱离实际问题去思考。所有技术都是围绕它要解决的问题而诞生的,因此技术的选型应该明确当前的场景是什么,要解决的问题是什么,此种技术是否能解决这个问题,有没有更简单、更易维护、更易上手的技术解决此问题。
没有万能的技术,只有解决对应问题的技术。任何一项高大上的技术用在了错误的场景,结果就是添油加醋,得不偿失

参考文档

MyCat 权威指南: http://www.mycat.org.cn/document/mycat-definitive-guide.pdf

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 210,914评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 89,935评论 2 383
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,531评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,309评论 1 282
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,381评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,730评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,882评论 3 404
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,643评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,095评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,448评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,566评论 1 339
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,253评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,829评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,715评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,945评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,248评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,440评论 2 348