一、存储系统
1.1 数据的生命周期
数据的产生—>数据的流动—>数据的持久化(合法性检验、组织数据、硬盘等存储)。在数据的生命周期中一般存在以下潜在问题:
- 数据库如何保证数据完整性?
- 数据库怎么处理多人同时修改的问题?
- 为什么用数据库,除了数据库还能存到别的存储系统吗?
- 数据库只能处理结构化数据吗?
- 有哪些操作数据库的方式,要用什么编程语言?
1.2 存储系统
一个提供了读写、控制类接口,能够安全有效地把数据持久化的软件,就可以称为存储系统。存储系统特点如下:
(1)性能敏感。很多大型后端系统架构中依赖有状态的、持久化的操作,需要频繁或者并发操作存储系统,需要使得存储系统的性能高效。
(2)易受硬件影响。存储系统处在软件架构的底层阶段,需要与硬件打交道,也就是说如果出现了更加高效的硬件,软件代码等需要跟着硬件的更新而进行重构或重写。
(3)代码即“简单”又“复杂”。“简单”表现在考虑性能方面,“简单”的代码让存储系统能够高效运转;“复杂”体现在对存储错误或异常的检查和捕获,在复杂的业务场景下,需要更多的异常处理代码以应对不同的业务情况。
RAID(Redundant Array Inexpensive Disks)技术
RAID技术的出现是为了降低数据存储成本、提高写入性能和提高存储安全性。
RAID 0:多块磁盘简单组合;数据条带化存储,提高磁盘带宽;没有额外的容错设计
RAID 1:一块磁盘对应一块额外镜像盘;真实空间利用率仅50%;容销能力强
RAID 0 与 RAID 1可以认为是两个极端。可以使用0+1或者1+0结合相得益彰。
二、数据库
关系:关系=集合=任意元素组成的若干有序偶对,反映了事务间的联系。
关系代数: 对关系作运算的抽象查询语言,如交集、并集、笛卡尔积。
SQL: 结构化查询语言,方便人类阅读关系代数的表达形式。
关系型数据库: 结构化数据友好;支持事务(ACID;支持复杂查询语言。
非关系型数据库: 半结构化数据友好;可能支持事务(ACID);可能支持复杂查询语言
数据库VS经典存储
2.1 结构化数据管理
假设有一条数据如下:
{
"user_name": "xiaoming"
"password": "helloworld"
"password_hint": "coding"
}
当写入关系型数据库时,表形式如下:
| id | user_name | password | password_hint |
|---|---|---|---|
| 0 | xiaoming | helloworld | coding |
| ... | ... | ... | ... |
当使用经典的存储结构时,需要写入文件,自行定义管理结构,比如:
可以看出,如果使用自定数据管理结构,整个数据管理流程,数据操作等会显得繁琐且低效。
2.2事务能力
数据库事务四大特性是指ACID,即原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。
原子性(Atomicity): 指的是一个事务(transaction)中的所有操作要么全部执行成功,要么全部失败回滚,不允许部分执行成功而部分失败。这是保证事务的完整性和一致性的基本要求。
一致性(Consistency): 指的是一个事务执行前和执行后都必须处于一致状态,即数据库中的数据应该满足所有的约束条件、触发器等。如果一个事务执行成功,那么数据库中的数据应该是合法的、正确的。
隔离性(Isolation): 指的是不同的事务之间应该相互隔离,一个事务的执行不应该对其他事务产生影响。多个事务并发执行时,应该保证它们之间的执行结果与串行执行的结果一致。
持久性(Durability): 指的是一个事务一旦提交,其修改的数据应该持久保存在数据库中,即使出现系统故障或者断电等异常情况,也不能丢失。持久性保证了数据的可靠性和安全性。
2.3 复杂查询能力
关系型数据库的复杂查询能力涉及到结构化查询语言(SQL),假设有一个业务例子:查询出名字以xiao开头,且密码提示问题小于10个字的人,并按性别分组统计人数。
SQL代码实现大致如下:
Select gender,count(*)from user
where user_name like 'xiao%'
and len(password_hint)<10
group by gender;
经典存储代码实现可能如下:
for each data {
if (user_name...&&password_hint...) {
// 找到符合条件的数据,保存在marked_list
}
}
for each in marked_list {
if (gender == ....) {
}
}
SQL查询可能只需要几行代码,简洁高效;经典存储的实现代码可能需要十几行,多个循环,多个if分支实现,更加麻烦。
三、主流存储产品
3.1 单机存储
单机存储系统是指数据存储在单个计算机或服务器上的存储系统,通常也被称为本地存储或本地文件系统。它是一种最简单的存储方式,用于存储少量数据或个人使用的数据。
本地文件存储
单机存储系统通常由操作系统提供,它通过管理计算机上的磁盘或其他存储设备来提供数据存储和访问功能。常见的单机存储系统包括文件系统,如Windows中的NTFS、Linux中的EXT4、sysfs、rootfs等。
Linux系统包含Index Node和Directory Entry两大数据结构
Key-value存储
常见数据结构:LSM-Tree,某种程度上牺牲读性能,追求写入性能。如:RocksDB
3.2 分布式存储
分布式存储系统在单机存储基础上实现了分布式协议,加入了大量网络交互。
分布式存储系统分为分布式文件存储系统和分布式对象存储
HDFS
HDFS(Hadoop Distributed File System) 核心特点:支持海量数据存储;高容错性;弱POSIX语义;使用普通x86服务器,性价比高。
HDFS官方文档结构图
Ceph
Ceph 的核心特点:一套系统支持对象接口、块接口、文件接口,但是一切皆对象;数据写入采用主备复制模型;数据分布模型采用CRUSH算法
Ceph结构
3.3 单机数据库
关系型数据库
关系型数据库主流产品有:Oracle、MySQL、PostgreSQL等。
关系型数据库的通用组件:
- Query Engine一负责解析query,生成查询计划
- Txn Manager-负责事务并发管理
- Lock Manager-负责锁相关的策略
- Storage Engine一负责组织内存/磁盘数据结构
- Replication一负责主备同步
关键内存数据结构:B-Tree、B+-Tree、LRU List等 关键磁盘数据结构:WriteAheadLog(RedoLog)、Page
非关系型数据库
非关系型数据库主流产品有:MongoDB、Redis、Elasticsearch
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交互
3.4 分布式数据库
分布式数据库是指将数据存储在多台计算机或服务器上,通过网络连接实现数据共享和协同处理的数据库系统。主要目的解决容量问题、弹性问题和性价比问题。
总结
存储系统
- 块存储:存储软件栈里的底层系统,接口过于朴素
- 文件存储:日常使用最广泛的存储系统,接口十分友好,实现五花八门
- 对象存储:公有云上的王牌产品,immutable语义加持
- key-value存储:形式最灵活,存在大量的开源/黑盒产品
数据库系统
- 关系型数据库:基于关系和关系代数构建的,一般支持事务和$QL访问,使用体验友好的存储产品
- 非关系型数据库:结构灵活,访问方式灵活,针对不同场景有不同的针对性产品
分布式架构
- 数据分布策略:决定了数据怎么分布到集群里的多个物理节点,是否均匀,是否能做到高性能
- 数据复制协议:影响IO路径的性能、机器故障场景的处理方式
- 分布式事务算法:多个数据库节点协同保障一个事务的ACID特性的算法,通常基于2pc的思想设计