高性能架构之数据库集群

第70篇

极客时间《从0开始学架构》课程笔记。

关系数据库目前还是各种业务系统中关键和核心的存储系统,在很多场景下高性能的设计最核心的部分就是关系数据库的设计。因此高性能架构模式的重点依然是高性能数据库集群的设计。

高性能数据库集群有两种方式:
1、读写分离,其本质是将访问压力分散到集群中的多个节点,但是没有分散存储压力。
2、分库分表,既可以分散访问压力,又可以分散存储压力。

一、读写分离

读写分离的基本原理是将数据库读写操作分散到不同的节点上。

读写分离基本架构

读写分离的基本实现:

  • 数据库服务器搭建主从集群,一主一从、一主多从都可以。
  • 数据库主机负责读写操作,从机只负责读操作。
  • 数据库主机通过复制将数据同步到从机,每台数据库服务器都存储了所有的业务数据。
  • 业务服务器将写操作发给数据库主机,将读操作发给数据库从机。

从以上4点可以看出,第3、4两步操作是实现重点,因此也带来两个问题:

问题1:主从复制延迟

一般主从复制延迟可能达到 1 秒或更长,如果业务服务器将数据写入到数据库主服务器后立刻(1 秒内)进行读取,此时读操作访问的是从机,主机还没有将数据复制过来,到从机读取数据是读不到最新数据的,业务上就可能出现问题。

常见解决方案

  1. 写操作后的读操作指定发给数据库主服务器
  2. 读从机失败后再读一次主机
  3. 关键业务读写操作全部指向主机,非关键业务采用读写分离

问题2:分配机制

将读写操作区分开,然后访问不同的数据库服务器,一般有两种方式:程序代码封装和中间件封装。

1、 程序代码封装

程序代码封装指在代码中抽象一个数据访问层(所以有的文章也称这种方式为“中间层封装”),实现读写操作分离和数据库服务器连接的管理。

特点:

  • 实现简单,而且可以根据业务做较多定制化的功能。
  • 每个编程语言都需要自己实现一次,无法通用,如果一个业务包含多个编程语言写的多个子系统,则重复开发的工作量比较大。
  • 故障情况下,如果主从发生切换,则可能需要所有系统都修改配置并重启。

2、中间件封装

中间件封装指的是独立一套系统出来,实现读写操作分离和数据库服务器连接的管理。中间件对业务服务器提供 SQL 兼容的协议,业务服务器无须自己进行读写分离。对于业务服务器来说,访问中间件和访问数据库没有区别,事实上在业务服务器看来,中间件就是一个数据库服务器。

特点:

  • 能够支持多种编程语言,因为数据库中间件对业务服务器提供的是标准 SQL 接口。
  • 要支持完整的 SQL 语法和数据库服务器的协议,实现比较复杂,细节特别多,很容易出现 bug。
  • 数据库中间件自己不执行真正的读写操作,但所有的数据库操作请求都要经过中间件,中间件的性能要求也很高。
  • 数据库主从切换对业务服务器无感知,数据库中间件可以探测数据库服务器的主从状态。

建议:一般情况下采用程序语言封装的方式,或者使用成熟的开源数据库中间件。如MySQL Router、Atlas。

二、分库分表

业务分库

业务分库指的是按照业务模块将数据分散到不同的数据库服务器。

问题

业务分库能够分散存储和访问压力,但同时也带来了新的问题。

  1. join 操作问题
    业务分库后,原本在同一个数据库中的表分散到不同数据库中,导致无法使用 SQL 的 join 查询。
  2. 事务问题
    原本在同一个数据库中不同的表可以在同一个事务中修改,业务分库后,表分散到不同的数据库中,无法通过事务统一修改。虽然数据库厂商提供了一些分布式事务的解决方案(例如,MySQL 的 XA),但性能实在太低,与高性能存储的目标是相违背的。
  3. 成本问题
    业务分库同时也带来了成本的代价,本来 1 台服务器搞定的事情,现在要 3 台,如果考虑备份,那就是 2 台变成了 6 台。

方案

因为用户规模不同,对于小公司初创业务,不建议一开始就这样拆分。对于业界成熟的大公司来说,最好在业务开始设计时就考虑业务分库。

分表

将不同业务数据分散存储到不同的数据库服务器,能够支撑百万甚至千万用户规模的业务,但如果业务继续发展,同一业务的单表数据也会达到单台数据库服务器的处理瓶颈。
因此需要分表,单表数据拆分有两种方式:垂直分表和水平分表

单表数据拆分

分表说明:

  1. 实际架构设计过程中不局限切分的次数,可以切一次、两次,也可以切很多次。
  2. 单表进行切分后,是否要将切分后的多个表分散在不同的数据库服务器中,可以根据实际的切分效果来确定,并不强制要求单表切分为多表后一定要分散到不同数据库中。

分表能够有效地分散存储压力和带来性能提升,但和分库一样,也会引入各种复杂性。

垂直分表

垂直分表适合将表中某些不常用且占了大量空间的列拆分出去。
垂直分表引入的复杂性主要体现在表操作的数量要增加。

水平分表

水平分表适合表行数特别大的表,有的公司要求单表行数超过 5000 万就必须进行分表,这个数字可以作为参考,但并不是绝对标准,关键还是要看表的访问性能。

水平分表会引入更多的复杂性,主要表现在下面4方面:路由、join操作、count()操作、order by 操作。

  • 1、路由
    水平分表后,某条数据具体属于哪个切分后的子表,需要增加路由算法进行计算,这个算法会引入一定的复杂性。

常见的路由算法有3种:范围路由、Hash路由、配置路由,优缺点对比表如下:

路由算法 定义 设计复杂点 优点 缺点
范围路由 选取有序的数据列(例如,整形、时间戳等)作为路由的条件,不同分段分散到不同的数据库表中 分段大小的选取。分段太小会导致切分后子表数量过多,增加维护复杂度;分段太大可能会导致单表依然存在性能问题 可以随着数据的增加平滑地扩充新的表 分布不均匀
Hash路由 选取某个列(或者某几个列组合也可以)的值进行 Hash 运算,然后根据 Hash 结果分散到不同的数据库表中 初始表数量的选取。表数量太多维护比较麻烦,表数量太少又可能导致单表性能存在问题 表分布比较均匀 扩充新的表很麻烦,所有数据都要重新分布
配置路由 增加路由表,用一张独立的表来记录路由信息 设计简单,容易扩充。在扩充表的时候,只需要迁移指定的数据,然后修改路由表就可以了 必须多查询一次,会影响整体性能;而且路由表本身如果太大(例如,几亿条数据),性能同样可能成为瓶颈
  • 2、join操作
    水平分表后,数据分散在多个表中,如果需要与其他表进行 join 查询,需要在业务代码或者数据库中间件中进行多次 join 查询,然后将结果合并。

  • 3、count()操作
    水平分表后,虽然物理上数据分散到多个表中,但某些业务逻辑上还是会将这些表当作一个表来处理。
    常见处理方式对比如下:

处理方式 操作方法 优点 缺点
count()相加 在业务代码或者数据库中间件中对每个表进行 count() 操作,然后将结果相加 实现简单 性能比较低
记录数表 新建一张表,表名为“记录数表”,包含 table_name、row_count 两个字段,每次插入或者删除子表数据成功后,都更新“记录数表” 性能要大大优于 count() 相加的方式 复杂度增加不少,对子表的操作要同步操作“记录数表”,增加了数据库的写压力,并且会出现数据不一致问题
  • 4、order by 操作
    水平分表后,数据分散到多个子表中,排序操作无法在数据库中完成,只能由业务代码或者数据库中间件分别查询每个子表中的数据,然后汇总进行排序。

分库分表的实现方法

分库分表具体的实现方式也是“程序代码封装”和“中间件封装”,但实现会更复杂。读写分离实现时只要识别 SQL 操作是读操作还是写操作,通过简单的判断 SELECT、UPDATE、INSERT、DELETE 几个关键字就可以做到,而分库分表的实现除了要判断操作类型外,还要判断 SQL 中具体需要操作的表、操作函数(例如 count 函数)、order by、group by 操作等,然后再根据不同的操作进行不同的处理。

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