写点什么

模块四:如何设计业务高性能高可用存储架构?-- 学习总结

作者:小鹿
  • 2021 年 11 月 21 日
  • 本文字数:4526 字

    阅读完需:约 15 分钟

数据库存储架构


数据库读写分离


【实现原理】

1. 数据库服务器搭建主从集群,一主一从、一主多从都可以。

2. 数据库主机负责读写操作,从机只负责读操作。

3. 数据库主机通过复制将数据同步到从机,每台数据库服务器都存储了所有的业务数据。

4. 业务服务器将读写操作发给数据库主机,将读操作发给数据库从机。

【如何判断要读写分离】

1. 业务量持续增长。

2. 先优化(优化索引,加入缓存)再重构。

复杂度分析

  1. 复制延迟;

  2. 任务分解

复制延迟应对方法


【应对方法 1 - 读写绑定】写操作后的读操作指定发给数据库主服务器。

【缺点】业务侵入很大,容易留坑。


【应对方法 2 - 二次读取】读从机失败后再读一次主机。

【缺点】如果有很多二次读取,将大大增加主机的读操作压力。


【应对方法 3 - 业务分级】关键业务读写操作全部指向主机,非关键业务采用读写分离。

【缺点】编码人员容易全部采用读写主机。

任务分解实现方式


程序代码封装模式

1. 实现简单,基于 JDBC 封装。

2. 维护简单,无部署,无需考虑高性能高可用。

3. 每个语言都要实现一遍。


中间件封装模式

1. 实现复杂,独立服务器,需要实现连接管理。

2. 维护复杂,需要独立部署,并且要考虑集群部署支持高性能高可用。

3. 跨语言。

数据库分库分表

主机写入性能瓶颈,主机存储容量瓶颈

数据库分库分表

  1. 数据分库

  2. 数据分表

数据分库


1. Join 问题

原本在同一个数据库中的表分散到不同数据库中,导致无法使用 SQL 的 Join 查询。

【解法】

1. 小表冗余

将一些小表在每个库中冗余一份,例如字典表。

2. 代码 Join

在代码里面实现 Join 功能。

3. 字段冗余

例如订单表直接记录商品类型。

2. 事务问题

表分散到不同的数据库中,无法通过事务统一修改。

【解法】

分布式事务。

【案例】

先扣商品库存,扣成功后生成订单,如果因为订单数据库异常导致生成订单失败,业务程序又需要

将商品库存加上。而如果因为业务程序自己异常导致生成订单失败,则商品库存就无法恢复了,需

要人工通过日志等方式来手工修复库存异常。

数据分表

1. 垂直拆分

按列拆分,优化单机处理性能,常见于 2B 领域超

多列的表拆分。

2. 水平拆分

按行拆分,提升系统处理性能,常见于 2C 领域超

多行的表拆分。

多大的表需要拆分?

1. B+Tree 的层数:3 层大约是 2000 万条;

2. Innodb buffer pool:2000 万数据,每条数据

100 字节,单表就 2G 了;

3. 数据量持续增长的表。

水平分表复杂度和应对方法

【路由问题】

路由算法进行计算数据归属。

【Count 操作】

如何计算 Count。

【Join 操作】

如何执行与其它表 Join。

【Order by】

如何执行 Order by。

水平分表伸缩瓶颈

1. 每个应用都需要连接所有的分片,当应用数量增多后,数据库连接会逐渐成为瓶颈。以 MySQL 为例,默认 100 连接,实测 50~100 连接性能最高,超过 200 后会显著下降。

2. 单个 Sharding-JDBC 的聚合操作会有性能瓶颈


数据库分布式事务

分布式事务算法 - - 2PC


阶段 1:单个参与者故障会导致整体事务失败。

阶段 2:事务协调者故障会导致整体状态不一致,参与者一直等待事务协调者指令,可能需要人工修复。

分布式事务算法 - - 3PC


1. Yes 丢了会导致协调者取消事务。

2. 部分 preCommit 丢了会导致部分参与者超时取消事务,其它参与者收到了 preCommit 消息,然后超时提交事务,因此造成脑裂。

3. Ack 丢了会导致参与者超时提交事务。

4. doCommit 丢失会导致参与者超时提交事务。

MySQL XA

【外部 XA】跨多 MySQL 实例的分布式事务,由应用程序代码作为 2PC 的事务协调者。

【内部 XA】跨同一实例多存储引擎的事务,由 Binlog 作为 2PC 的事务协调者。

思维导图


存储架构模式 - 复制架构


高可用关键指标

存储类问题处理框架图


高可用存储几个核心指标


【RPO】

Recovery Point Objective,恢复点目标,指”最大可接受的数据损失“,因为数据备份和复制都是有时间限制的,不可能做到绝对实时。

【RTO】

Recovery Time Objective,恢复时间目标,指“最大可接受的系统恢复所需时间”,因为定位、处理、恢复需要时间。

【WRT】

Work Recovery Time,工作恢复时间,指“系统恢复正常后,恢复业务所需的时间”,因为要进行各种业务检查、校验、修复。

【MTD】

Maximum Tolerable Downtime ,最大可容忍宕机时间,等于 RTO + WRT。


主备 & 主从架构

主备复制 & 主从复制

主备复制(数据可恢复)

本质:通过冗余来提升可用性,通过叠加来提升读性能。

变化:备机是否提供复制功能,备机部署地点,主从主备混合部署。


主从复制(数据可恢复 + 高性能读)

优点:实现简单,只需要数据复制,无状态检测和角色切换。

缺点:需要人工干预,RTO 比较大。

主备级联复制

变化:

备机作为复制源,例如图中备机 1 是备机 2 的复制源。

优点:

主机故障后,切换备机 1 为主机,方便快捷,直接修改配置即可

(图中虚线部分),无需修改备机 2 的配置,无需判断备机 1 和备

机 2 的数据覆盖问题。

缺点:

备机 1 对备份非常关键,备机 1 宕机会导致两台备份机都备份失败。

应用:

MySQL、Redis 支持这种模式。

主备架构的灾备部署

【场景 1】

IDC-1 和 IDC-2 在同一个城市,可以应对机房级别的灾难。

【场景 2】

IDC-1 和 IDC-2 不在同一个城市,可以应对城市级别的灾难。


主从架构的灾备部署

【场景 1】

IDC-1 和 IDC-2 在同一个城市,可以应对机房级别的灾难。

【场景 2】

IDC-1 和 IDC-2 不在同一个城市,可以应对城市级别的灾难。

双机切换架构

主备切换

优点:可以自动实现故障恢复,RTO 短。

缺点:实现复杂,需要实现数据复制、状态检测、故障切换(参考模块 2 第 3 课)、数据冲突处理。

应用:内部系统、管理系统。

主从切换

整体和主备切换类似,差异点在于“切换阶段”,只有主机提供读写服务,主机性能有风险。

集群选举架构

集群选举

优点:可以自动实现故障恢复,RTO 短,可用性更高。

缺点:实现复杂,需要实现数据复制、状态检测、选举算法、故障切换(参考模块 2 第 3 课)、数据冲突处理。

应用:通用,例如 Redis、MongoDB 等。

思维导图

存储架构模式 - 分片架构和分区架构

分片架构

分片架构的本质

  1. 只有主机承担写,写性能会存在瓶颈;

  2. 每台机器保存全量数据,存储存在瓶颈

分片架构本质

通过叠加更多服务器来提升写性能和存储性能。


分片架构设计核心

  1. 分片规则:数据按照什么规则分片;

  2. 路由规则:业务服务器如何找到数据。

分片架构设计核心 - - 分片规则

核心原则

选取基数比较大的某个数据键值,让数据均匀分布,避免热点分片。

【基数 Cardinality】

被选的数据维度取值范围。

【均匀】

数据在取值范围内是均匀分布的。

分片数据

【主键】

适合主业务数据,例如数据库分片常用的用户 ID,订单 ID,Redis 分片的 key,

MongoDB 的文档 ID。

【时间】

适合流水型业务,例如创建日期,IoT 事件,动态。

分片规则

【Hash 分片】

1)sharding key = hash(原始键值)分布均匀,但是不支持范围查询

2)扩容服务器麻烦,需要做数据迁移

【范围分片】

1)分布可能不均匀,支持范围查询

2)方便扩容新服务器,无需迁移历史数据

分片架构设计核心 - - 路由规则

分片动态路由 - - 配置中心

1. 由专属的配置中心记录分片信息,客户端需要向配置中心查询分片信息,然后发起读写操作。

2. 可以支持超大规模集群,节点数量可以达到几百上千。

3. 架构复杂,一般要求独立的配置中心节点,配置中心本身又需要高可用,例如 MogoDB 用的是 replica set,HDFS 用的是 ZooKeeper(注意:HDFS 2.0 版本以前的 Namenode 是单点)。

分片动态路由 - - 路由转发

  1. 每个节点都保存所有路由信息,客户端请求任意节点皆可;

  2. 架构相对简单一些,一般通过 gossip 协议来实现分片信息更新;

  3. 无法支持超大规模集群,Redis 官方建议 1000 以内,实际集群数量建议 100 以内(为什么?)。


分片架构高可用方案 1 - - 独立备份

【原理】

每个分片有独立的备份节点,可以用主备、主从、集群选举等方式实现。

【优缺点】

1. 实现简单;

2. 机器硬件成本比较高。

【应用】

存储系统已经支持节点级别的复制。

分片架构高可用方案 2 - - 互相备份


【原理】

分片之间的节点互相备份。

【优缺点】

1. 实现复杂;

2. 机器硬件成本相对来说低,互相利用。

【应用】

存储系统支持数据块级别的复制。

分区架构

分区架构全局路由 - - S DNS 和 和 GSLB

DNS:标准协议,通用,但基本只能实现就近接入的路由。

GSLB:非标准,需要独立开发部署,功能非常强大,可以做状态监测、基于业务规则的定制路由。

分区架构备份策略 - - 集中式

1. 设计简单,各分区之间并无直接联系,可以做到互不影响。

2. 扩展容易,如果要增加第四个分区(例如,西安分区),只需要将西安分区的数据复制到成都

备份中心即可,其他分区不受影响。

3. 成本较高,需要建设一个独立的备份中心。

分区架构备份策略 - - 互备式

1. 设计比较复杂,各个分区除了要承担业务数据存储,还需要承担备份功能,相互之间互相关联

和影响。

2. 扩展麻烦,例如增加一个武汉分区。

3. 成本低,直接利用已有机房和网络。

分区架构备份策略 - - 独立式

  1. 设计简单,各分区互不影响。

  2. 扩展容易,新增加的分区只需要搭建自己的备份中心即可。

  3. 成本高,每个分区需要独立的备份中心,备份中心的场地成本是主要成本。


思维导图


设计存储架构


存储架构设计总体思路

存储架构设计三个步骤


1.估算性能需求

【任务】基于具体的业务场景来估算性能需求,包括存储量、读写性能等。

【挑战】1. 不知道如何估算;2. 担心估算不准。

2. 选择存储系统

【任务】根据技术储备、方案优缺点选择合适的存储系统。

【挑战】1. 不知道有哪些存储系统;2. 知道但是不知道怎么选。

3. 设计存储方案

【任务】基于选择的存储系统,设计其具体的存储方案,如果发现不行,回到步骤 2 再换一个。

【挑战】1. 不知道如何设计存储方案。

估算存储性能需求

性能估算步骤

用户量预估

规划:根据成本、预算、目标等确定。

推算:基于已有数据推算。

对比:跟已有标杆进行对比


用户行为建模

行为:采取某种行为的用户数量。

数量:采取某种行为的用户数量

频率:用户某种行为的频率。

存储性能需求计算

数据量:对数据的读写请求量(TPS/QPS)。

请求量:对数据的读写请求量(TPS/QPS)。

预留量:预留的增长空间。

说明和技巧:

  1. 并不是所有数据都一定要用同样的存储方式,例如当前数据和历史数据可以分开存储。

  2. TPS/QPS 需要计算出以秒为单位的数值,并且计算“平均值”和“峰值”。

  3. 预留增长空间不能太大也不能太小,如果能做到线性伸缩是最好的。

选择存储系统

存储架构选择逻辑

常见存储系统分类

选择合适的存储系统

技术本质:挑选应用场景和系统本质契合的系统

技术储备:挑选熟悉的。

综合考虑:可维护性、成本、成熟度等。

什么是技术本质?

系统的 DNA,有别于其它系统的典型特征。例如:MongoDB 是文档数据库,MySQL 是关系数据库,Redis 是 Remote dictionary Server,Elastcisearch

是倒排索引搜索引擎,HBase 是“sparse, distributed, persistent multidimensional sorted map”……

技术本质有什么影响?

技术本质决定了其核心应用场景和优缺点,例如 MongoDB 是文档数据库,优点是 Schemaless,缺点是事务支持不好,Elasticsearch 是搜索引擎而不是存

储引擎(虽然可以做存储)。

设计存储方案

存储方案设计三个步骤


1. 设计数据结构

选择或者设计具体的数据结构,例如如何设计具体的表,选择 Redis 的哪个数据结构。

2. 验证读写场景

将数据结构放到具体的场景进行验证,设计读写具体如何执行(Rule)。

3. 评估读写性能

评估具体场景下的数据结构设计是否满足性能需求,不满足则重新设计。


思维导图


用户头像

小鹿

关注

还未添加个人签名 2020.04.16 加入

还未添加个人简介

评论

发布
暂无评论
模块四:如何设计业务高性能高可用存储架构?-- 学习总结