数据库 | 青训营笔记

70 阅读7分钟

存储与数据库

存储 & 数据库

存储系统

  • 一个提供了读写、控制类接口,能够安全有效地把数据库持久化的软件,可以成为存储系统
系统特点
  • 作为后端软件的底座,性能敏感
  • 存储系统软件架构,容易受硬件影响
  • 存储系统代码,即简单又复杂
RAID 技术
  • 出现背景

    • 单块大容量磁盘的价格 > 多块小容量磁盘
    • 单块磁盘的写入性能 < 多块磁盘的并发写入性能
    • 单块磁盘的容错能力有限,不够安全
  • RAID 0

    • 多块磁盘简单组合
    • 数据调带化存储,提高磁盘带宽
    • 没有额外的容错设计
  • RAID 1

    • 一块磁盘对应一块额外外镜像盘
    • 真是空间利用率仅50%
    • 容错能力强
  • RAID 0 + 1

    • 结合了 RAID 0 和 RAID 1
    • 真是空间利用率仅50%
    • 容错能力强,写入带宽好

数据库

概览
  • 关系 = 集合 = 任意元素组成的若干有序偶对反映了事务间的关系
  • 关系代数 = 对关系做运算的抽象查询语言
  • SQL = 一种 DSL = 方便人类阅读的关系代数表达形式
特点
  • 关系型数据库时存储系统,但是在存储之外,有发展出其他能力

    • 结构数据友好
    • 支持事务
    • 支持复杂查询语言
  • 非关系型数据库也是存储系统,但是一般不要求严格的结构化

    • 半结构化数据友好
    • 可能支持事务
    • 可能支持复杂查询语言

主流产品

单机存储
  • 单机存储 = 单个计算机节点上的存储软件系统,一般不涉及网络交互
本地文件系统
  • Linux:一切皆文件

  • 文件系统的管理单元:文件

  • 文件文件接口:文件系统繁多,如 Ext2/3/4,sysfs,rootfs 等,但是都遵循 VFS 的统一抽象接口

  • Linux 文件系统的两大数据结构:Index Node & Directory Entry

    • Index Node

      • 记录文件元数据,如 id、大小、权限、磁盘位置等
      • inode 是一个文件的唯一标识,会被存储到磁盘上的 inode 的总数在格式化文件系统时就固定了
    • Directory Entry

      • 记录文件名、inode 指针、底层关系(parent)等
      • dentry 是内存结构,与 inode 的关系是 N : 1(hardlink 的实现)
key-value存储
  • 常见使用方法:put(k, v) & get(k)
  • 常见数据结构:LSM-Tree,某种程度上牺牲读性能,追求写入性能
  • 拳头产品:RocksDB
分布式存储
  • 分布式存储 = 在单机存储基础上实现了分布式协议,涉及大量网络交互
HDFS
  • 大数据时代的基石

  • 专用的高级硬件很贵,同时数据存量很大,要求超高吞吐

  • 核心特点

    • 支持海量数据存储
    • 高容错性
    • 弱 POSIX 语义
    • 使用普通 x86 服务器,性价比高
Ceph
  • 开源分布式存储系统的万金油

  • 核心特点

    • 一套系统支持对象接口、块接口、文件接口,但是一切皆对象

    • 数据写入采用主备复制模型

    • 数据分布模型采用 CRUSH 算法

      • CRUSH = HASH + 权重 + 随机抽签
单机数据库
  • 单机数据库 = 单个计算机节点上的数据库系统
  • 事务在单机内执行,也可能通过网络交互实现分布式事务
关系型数据库
  • 商业产品 Oracle 称王,开源产品 MySQL & PostgreSQL 称霸

  • 关系型数据库的通用组件

    • Query Engine - 负责解析 query、生成查询计划
    • Txn Manager - 负责事务并发管理
    • Lock Manager - 负责锁相关的策略
    • Storage Engine - 负责组织内存 / 磁盘数据结构
    • Replication - 负责主备同步
  • 关键内存数据结构:B-Tree、B+-Tree、LRU List 等

  • 关键磁盘数据结构:WeiteAheadLog(Redo log)、Page

非关系型数据库
  • ES

    • 面向文档存储
    • 文档可序列化为 JSON、支持嵌套
    • 存在 index、index = 文档的集合
    • 存储和构建索引依赖 Lucene 引擎
    • 实现了大量搜索数据结构 & 算法
    • 支持 RESTFUL API,也支持弱 SQL 交互
  • mongoDB

    • 面向文档存储
    • 文件可序列化为 JSON、BSON,支持嵌套
    • 存在 collection,collection = 文档的集合
    • 存储和构建索引能力依赖的 wiredTiger 引擎
    • 4.0 后开始支持事务(多文档、跨分片多文档等)
    • 常用 client / SDK 交互,可通过插件转移支持弱 SQL
  • Redis

    • 数据结构丰富(hash 表、set、zset、list)
    • C语言实现、超高性能
    • 主要基于内存,但支持 AOF / RDB 持久化
    • 常用 redis-cli / 多语言 SDK 交互

小总结

存储系统
  • 块存储:存储软件栈里的底层系统,接口过于朴素
  • 文件存储:日常使用最广泛的存储系统,接口十分友好,实现五花八门
  • 对象存储:公有云上的王牌产品,immutable 语义加持
  • key-value 存储:形式最灵活,存在大量的开源 / 黑盒产品
数据库系统
  • 关系型数据库

    • 基于关系和关系代数构建的,一般支持事务和 SQL 访问,使用体验友好的存储产品
  • 非关系型数据库

    • 结构灵活,访问方式灵活,针对不同场景有不同的针对性产品

深入理解 RDBMS

DBMS 数据模型

网状模型层次模型关系模型
优势- 能够直接描述现实世界 - 存储效率较高- 结构简单 - 查询效率高 - 可以提供较好的完整性支持- 实体及实体间的联系都通过二维表结构表示 - 可以方便的表示 M : N 关系 - 数据访问路径对用户透明
劣势- 结构复杂 - 用户不易访问 - 访问程序设计复杂- 无法表示 M : N 的关系 - 插入、删除限制多 - 遍历子节点必须经过父节点 - 访问程序设计复杂- 关联查询效率不够高 - 关系必须规范化

SQL 语言

  • 语法风格接近自然语言
  • 高度非过程化
  • 面向集合的操作方式
  • 语言简洁,易学易用

SQL 引擎

Parser
  • 解析器一般分为词法分析、语法分析、语义分析等步骤
Optimizer
  • 基于规则的优化

    • 条件化简

    • 表连接优化

    • 总是小表先进行连接

    • Scan 优化

      • 唯一索引
      • 普通索引
      • 全表扫描
    • 数据库索引:是数据库管理系统中的数据结构,以协助快速查询、更新数据库表中的数据,目前数据库中常见的索引是通过 B+ 树实现的

Executor
  • 每个 Operator 调用 Next 操作,访问下层 Operator,获得下层 Operator 返回的一行数据,经过计算之后,将这行数据返回给上层

  • 优点

    • 每个算子独立抽象实现,相互之间没有耦合,逻辑结构简单
  • 缺点

    • 每计算一条数据有多次函数调用开销,导致 CPU 效率不高

事务引擎

  • Undo Log 是逻辑日志,记录的是数据的增量变化,利用 Undo Log 可以进行事务回滚,从而保证事务的原子性,同时也实现了多版本并发控制(MVCC),解决读写冲突和一致性的问题

  • MVCC 的意义

    • 读写互不阻塞
    • 降低死锁概率
    • 实现一致性读
  • Undo Log 在 MVCC 的作用

    • 每个事务有一个单增的事务 ID
    • 数据库的行记录中包含了 DB_ROW_ID,DB_TRX_ID,DB_ROLL_PTR
    • DB_ROLL_PTR 将数据行的所有快照记录都通过链表的结构串联了起来
  • 如何保证事务结束后,对数据的修改永久的保存

    • 方案一

      • 事务提交前页面写盘
    • 方案二(WAL)

      • redo log 是物理日志,记录的是页面的变化,它的作用是保证事务持久化,如果数据写入磁盘前发生故障,重启 MySQL 后会根据 redo log 重做

实战

大流量 - Sharding
  • 问题背景

    • 单节点容易成为瓶颈
    • 单机数量容易上限
  • 解决方案

    • 业务数据进行水平拆分
    • 代理层进行分配路由
  • 实施效果

    • 数据库写入性能线程扩展
    • 数据库容量线性扩展
流量徒增 - 扩容
  • 问题背景

    • 活动流量上涨
    • 集群性能不满足要求
  • 解决方案

    • 扩容 DB 物理节点数量
    • 利用影子表进行压测
  • 实施效果

    • 数据库集群提供更高的吞吐
    • 保证集群可以承担预期流量
流量徒增 - 代理连接池
  • 问题背景

    • 突增流量导致大量建联
    • 大量建联导致负载变大,延时上升
  • 解决方案

    • 业务侧预热连接池
    • 代理侧预热连接池
    • 代理侧支持连接队列
  • 实施效果

    • 避免 DB 被突增流量打死
    • 避免代理和 DB 被大量建联打死
稳定性 & 可靠性
3AZ 高可用
  • 三机房部署

    • 机房级别容灾
    • 机房级别流量调度
  • proxy

    • 读写分离,分库分类
    • 限流,流量调度
  • 监控报警

    • 实施监控集群运行状态
    • 提前上报集群风险
  • HA

    • High Availability
    • 实施监控 DB 运行状态
    • 宕机快速切换
HA 管理
  • 问题背景

    • db 所在机器异常宕机
    • db 节点异常宕机
  • 解决方案

    • ha 服务监管、切换宕机节点
    • 代理支持配置热加载
    • 代理自动屏蔽宕机读节点
  • 实施效果

    • 读节点宕机妙计恢复
    • 写节点宕机 30s 内恢复服务

TOS 对象存储

对象存储 vs 分布式文件系统

海量易用便宜
分布式文件系统 HDFS- 支持PB -> EB海量存储 - 文件数量收到Name Node 限制- 伪 Posix 文件接口,开发略复杂 - 非云原生,搭载维护较麻烦 视频 / 图片相关生态接入略复杂- 使用普通 x86 服务器,成本低
对象存储 TOS- 支持 > EB 海量存储 - 对象数量无限制- Restful HTTP 接口,开发极其简单 - 云原生,按需申请使用 - 视频 / 图片相关生态丰富- 使用普通 x86 服务器 - 具备冷热数据分级存储能力,成本更低