存储与数据库 | 青训营笔记

50 阅读5分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 十五 天

存储 & 数据库

  • 前言
  • 存储&数据库简介
  • 主流存储系统剖析
  • 发展方向

前言

一条数据从产生,到数据流动、最后到持久化的全生命周期都发生了什么?

用户从前端输入数据,由前端通过网络发送到后端系统;

后端系统在解析并校验前端发送过来的数据后将数据写入数据库;

数据库接收到数据后,将数据从内存持久化到硬盘。

在数据持久化的过程中会出现什么问题?

  • 数据丢失
  • 数据并发修改,引发数据一致性问题
  • 数据迁移,数据库不兼容问题
  • 只能处理结构化数据

存储&数据库简介

什么时存储系统?

一个可以提供读写、控制类接口,能安全有效的把数据持久化的软件,即存储系统。

数据如何从应用到存储介质?

应用开启IO将内存数据拷贝到存储介质的缓存内,再由存储介质写入存储单元。

RAID 磁盘阵列

  • RAID 0: 把要储存的每一个档案切割成许多资料区块 后,以分散的方式同时存放到各个硬盘里

    • 读写速度翻倍
    • 没有容错设计
  • RAID 1: 把每一个要储存的档案,分别同步存放在主硬盘和镜像硬盘里

    • 数据容错能力强
    • 数据冗余,利用率仅为50%
  • RAID 01: 结合RAID 0 和 RAID 1

    • 写入快,容错强
    • 空间利用率50%
  • ...

关系是什么?

关系:一张二维表,每个关系都具有一个关系名,也就是表名。

关系可以理解为事物的特征集合,由任意元素组成的若干有序偶对反映了事物间的关系。

主流存储系统剖析

关系型数据库

原生支持事务,支持关系查询

  • Oracle:商用数据库,数据库届头牌
  • MySQL:开源数据库一哥
  • PostgreSQL:后起之秀,常被二次开发用于企业自研数据库内核

非关系型数据库

没有关系型数据库的关系约束,数据结构千奇百怪,schema相对灵活

  • MongoDB:列式数据库

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

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

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

分布式数据库

HDFS

HDFS,堪称大数据时代的基石

——时代背景:专用高级存储硬件昂贵,数据存量大,超高数据吞吐需求

核心特点:

  • 支持海量数据存储
  • 高容错性
  • 弱POSIX语义
  • 兼容X86,超高性价比

Ceph

Ceph,开源分布式存储系统里的「万金油」

核心特点:

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

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

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

    • CRUSH:hash + 权重 + 随机抽签

发展方向

  • 软件架构变更:Bypass OS kernel

  • AI增强:智能存储格式转换

  • 硬件革命

    • 存储介质:Persistent Memory
    • 计算单元:CPU -> 超多核,核心堆积;GPU -> 多核,大显存;DPU,异构计算缓解CPU工作负载
    • 网络硬件:可编程交换机、RDMA网络

课后思考

写入存储系统的粒度太大,会不会导致数据原子性问题?例如一次性写100MB,如果系统突然crash,会不会只有一部分数据持久化了,另一部分丢失了?如果要解决原子性问题,一般会设计什么机制?

存储系统支持事务时,写入粒度大并不会影响存储系统的原子性;

系统突然宕机会导致数据一部分持久化而一部分丢失的问题。

解决原子性问题一般引入事务机制,开启事务后只有所有操作都会绑定,要么一起成功,要么一起失败回滚。

在从应用程序到存储介质的链路上,无论读还是写,数据可能要被拷贝好几次,这几次拷贝能不能去掉?如果我们去掉大部分拷贝操作,会有什么副作用,要怎么缓解副作用?

可以省去部分拷贝的动作,可以参考“零拷贝”;

零拷贝会带来系统安全问题,应用程序可控性差,缓解办法:sendfile,提供安全接口

一个关系型数据库大概率是会被并发访问的,如果要保证并发安全,除了在行数据上加悲观锁还有其他方式吗?

乐观锁:CAS,失败自旋

MVCC:版本控制

并行改串行:将并行访问转换为串行访问

在数据库领域,把数据按行存和按列存各有好处,你能从性能优先的角度设计出一种混合存储格式吗?

ps:简单暴力的设计

分别存储一份行数据与列数据,按场景选择查询要走的库;更新是并发更新两个库。