数据密集系统设计
一、计算密集与数据密集
1. 计算密集
有限数据,复杂计算,产生计算结果
2. 数据密集
海量数据查询/多数据系统综合协同/负责业务流程处理
OLTP(Online Transaction Process): 事务性处理,一次业务请求,得到结果/产生数据,多为在线业务系统,注重时效。
OLAP (Online Analysis Process):交互式分析,不断递进,多为离线分析系统,对时效依赖要求性没那么高。
二、系统指标
1. 可靠性
1)结果符合预期-功能正确
2)应对非预期输入【参数错误,权限认证】-容错
3)应对流量波动-弹性
硬件故障具有独立性,软件故障具有关联性,
2. 扩展性
AKF立方体,流量扩展维度-应用复制,应用维度-应用拆分,数据维度-数据分区。
3. 可维护性
三、数据模型
系统由多层模型组成,每层提供本层的简单抽象,隐藏实现的复杂性,上层组装下层的api,以高效协作。
二、数据存储查询
1. 数据库的基本功能
将指定数据存放起来,并能根据特定条件查询出特定的数据或返回不存在。【最简单的数据库可以用几行shell(echo/grep)实现】
2. 关系数据库/NoSql数据库/融合趋势
一对一关系:KV查询
一对多关系:索引查询
多对多关系:多表联合查询【一个人有多种职业,一个职业也可以对应多个人。】
3. 行存储/列存储
行存储,一行作为一个基本单位,物理上一行时放在一起的。要读取一行中的某列,必须先读取整行,在提取其中的一列。
列存储,一行可以有多列,以一列作为基本存放单位,相邻多行的同一列在物理上时临近的。要读取一行中的某一列,可以直接读取那一列所在的磁盘位置。
对于大数据分析场景,扫描提取一个范围区间的多行的某几列值,相当于在磁盘上的临近位置读取数据,相比行存储效率要高不少。
4. 数据库与数据仓库
数据仓库和数据库本来没什么不同,但是随着olap和oltp的分离,为了避免离线分析对在线业务的影响,离线任务对数据库的访问需求不能和在线业务共用,且离线任务需要的数据更全,更多,来源更广,一般将多来源数据流通过汇总后,形成适合离线分析使用的数据仓库中的数据格式。
5. 持久化与内存数据库
内存数据库,一般用作缓存,要求所有数据加载到内存。但内存数据库不意味着数据不需要持久化,也需要落盘的,以避免数据丢失和停机重启。但是内存数据库不用考虑从磁盘搜索指定数据,不用考虑磁盘索引等。所以不用设计lsm/btree等数据索引方式,只用考虑快速加载等就可以了。
6. LSM
实现
log structure merge,内存排序,然后快照落盘。磁盘数据分层合并。内存存放稀疏索引,块内数据有序。
查询数据时,两个层面,1. 稀疏索引确定数据块,块内二分查找。2. 先查内存中,内存中没有再查磁盘中。为了提高查询效率,减少无效的查找,采用bloom过滤器。
优点
1. 稀疏索引和全索引相比,节省内存,避免数据扩张索引挤爆内存
2. 数据局部有序,与全哈希策略相比,更容易命中缓存。【访问临近数据的概率相对较大】
3. 经常整理合并,磁盘碎片较少。
4. 数据写,磁盘顺序写,效率更高。
缺点
1. 磁盘上不同layer的数据中,内存数据中,会包含重复数据,
2. 每次查找必须挨着找一遍,浪费计算资源。
3. 后台数据整理线程,耗费计算资源。
4. 整理过程中,合并块数据double,资源占用翻倍
4. 后台整理造成写放大问题。
适合数据顺序读写的场景,尤其是物理磁盘,顺序读写比随机读写性能优势巨大。hbase,redis,mongo,scalla等nosql 都是采用此底层存储方式。
7. Btree
实现
一棵平衡树,每个非叶子结点将本结点所涵盖的区域分成多个子节点【一般256/512】,并包含指向子节点的指针。叶子结点包含实际的数据,直接落在磁盘上的某个位置。查找时,一层一层找下来,每层二分查找,便可找到最终的叶子结点上的数据。叶子节点一般存放一个磁盘页,4k。
4层btree举例,可以容纳数据量 512*512*512*512*4*1024=256T
优点
相比lsm,读数据效率更高,不用后台整理数据,不存在数据重复资源占用多的问题。
不存在多副本,加锁更容易,事务能力强。
缺点
数据覆盖时,如果原有数据空间不够,需要更改位置,并修改引用,容易造成磁盘碎片。
传统数据库通用存储方式,sql数据库都采用此方式。
8. 空间多维数据索引
多位数据的存放,采用多维数据分割包含的策略,外层包含内层,形成一个搜索树,R树/KD树等。

9. 物理磁盘/SSD
磁盘访问耗时,一次物理询盘4-10ms之间,一次ssd磁盘访问0.xms。
10. 事务
10.1ACID
针对单个数据库的不同操作间的要求, 一个操作可以是修改一个数据,也可以是一组连续动作修改一组数据【事务】。
原子性,同一个操作要么完全成功要么完全失败,不存在中间状态。【2PL,两节点加锁】
一致性,不是多节点间同一份数据的一致,而是同一个节点一组关联数据间的一致性。【事务】
隔离性,不同操作间相互隔离,不会相互影响。【并发隔离,加锁,CAS】
持久性。 提交后数据不会丢失。【防机器崩溃,WAL】
锁:
锁库:最严格的,影响范围大,不实用
锁表:影响一个表
锁行:指影响某一行
锁索引:影响符合索引条件的所有行,适合同时读写符合某一条件的多份数据,影响范围小于锁表。实现难度大。【条件之间有包含关系,是否能穷举,是否有案例?】
悲观锁:【适合多写少读场景】
读写锁:读共享,写独占。
独占锁: 完全互斥。
乐观锁:【适合多读少写场景】
写入时检查是否符合预期,如果不符合返回错误,符合则写入【CAS】
10.2 读-提交
只有提交后的数据才对其他读或写操作可见。
脏读/脏写。
实现方式:1. 行锁,可以防止脏写,但如果用在防止脏读,性能受不了。解决方式为写时保存新旧两个版本的数据,写只锁新数据,写之间互斥,不影响读旧的值。写提交后,替换旧的值。
此处读不加锁,就容易造成读倾斜,意思是读事务中的多个动作,有可能分别读到写事务提交之前和之后的值,综合起来数据就不符合实际,是一个错的数据。解决方案为快照隔离。
10.3 快照级别隔离
每条数据保存多个版本,每个写事务分配一个ID,写入的数据的版本带上当前事务的ID。读事务只能读到本事务开始之前的所有已提交事务的数据。
多版本方案还可以实现删除回滚。【删除只是标记删除】
事务不能解决 更新丢失问题【两个线程同时递增计数器】,CAS可以,但CAS不能解决ABA问题,但串行化可以。
ABA的定义见:https://blog.csdn.net/huangquan__/article/details/116241700
10.4 串行化
串行化算法,两阶段加锁 2PL。读加共享锁,写加独占锁。
SSI 可串行化快照
乐观锁+多版本控制。每次基于一个快照版本写入,提交前检测是否过期,过期则失败,不过期则提交。
二、分布式系统
1. 数据密集分布式系统出现的原因
高可用/低延迟/可扩展
2. CAP
针对分布式系统不同节点间相互配合的三个要求。
一致性, 多节点返回数据状态一致。
可用性, 任何情况都有结果返回。
分区容忍性,节点间失去联系时,系统仍可用。
CA系统,允许脑裂,不管分区性,失去链接的节点不管状态。
CP系统,允许节点不返回,不管可用性,不能同步时,系统不可用,直到全部同步为止。
AP系统,允许不一致,不管一致性,允许不同节点返回不同数据。
3. 分布式事务:
2PC【两阶段提交】
1. 提交数据,2. 询问是否可以提交,3. 发出提交/回滚指令,4. 提交或者回滚。
主者决定第三步后,必须完成动作3,机器崩溃后也必须有恢复机制,不能回头。
从节点回复2后,必须等待3的指令并执行。如果主节点死掉,也必须等,并执行3的指令。不能回头。
由于有用不回头的状态,有时候可能造成死锁,必须认为介入。
3. 一致性/最终一致性/弱一致性/线性一致
分布式系统中,除非应用分布式事务,否则强一致性很难达成。但分布式事务性能较低,难以大规模使用。
最终一致性,只保证多节点最终会同步完成,但时间延迟不定,系统设计时应考虑业务需求和同步延迟的匹配。
弱一致性,1. 读自己的写,【是对特定业务的一些取巧操作,例如看自己的数据被路由到主节点,看别人的数据才路由,避免自己刚刚修改的数据看不到的问题给用户造成困扰。】2. 单调读一致性。【每个用户路由到固定的节点】
线性一致:各节点间可能状态不同,但保证状态改变的顺序是一致的。【版本号保证】【聊天程序,聊天上下文不能乱序,否则造成混乱】
4. 数据复制
4.1 主从复制
主写从读,只有一个主节点提供写功能。同步复制+异步复制,合理配置解决高可用和性能的权衡
4.2 多主复制
多个主节点,都负责写入,然后相互复制。
写冲突问题:1. 避免冲突,2. 合并冲突【时间戳,最后写入获胜,容易丢数据,节点时钟不同步】
3. 推给应用层解决。
4.3 无主复制
同时写多副本,同时读多副本,少数服从多数。也可以读时修复。
5. 并发【多客户端写入一个节点】
两件事情没有因果依赖关系,相互无法感知,就可以视为可并发事件,也可以说是独立事件。
LastWriteWin:丢弃并发写入,只保留最新值。
多客户端并发写入数据库,如何合并。可以采用多版本号,每次写入都要发送自己依赖的版本号,和新的值,数据库收到后用请求值分配最新的版本号,并覆盖原版本号。读取时,返回所有未被覆盖的版本号的值,客户端负责合并,并作为自己下次写入的基础。
6. 数据分区
1. 基于关键字的分区,拥有过良好的区间查询性,容易导致热点
2. 基于关键字哈希的分区,区间查询性能不好。
3. 复合主键,第一列哈希,其他列排序。适合一对多的模式。【cassandra】
二级索引:
1. 索引基于文档分区,查询索引时查询所有分区
2. 索引基于词条分区,查询索引时只需要查询一个分区。写入时需要更新多分区索引,慢。同步更新依赖事务不现实,多用异步更新模式。
7. 一致性
6.1 因果一致性,偏序
如何捕获因果关系,cas的用法,ssi的用法。
捕获全局因果关系难度不可想象。
6.2 线性一致性,全序,无并发。
序号排序,逻辑时钟
6.3 全序广播
所有节点所有操作遵循一套版本号,每个操作广播,每个节点将自己当前版本号返回,当前节点在最高版本号基础上加1,如此往复。【阻塞,节点多了不行,网络不稳定造成】
7. 冲突解决方案
7.1 2pl 解决单节点事务的串行化隔离问题,解决单节点并发问题。2pc 解决多节点分布式事务的原子提交问题。2pc中,参与者准备请求回复OK/FAIL,和协调者提交/放弃 决定的不可撤销性,保证了多节点分布式系统的原子提交。2pc+2pl合作才能解决 并发+分布式的问题。
7.2 快照隔离,多版本合并
7.3 乐观锁+快照隔离(可串行化快照隔离SSI)
8. 共识
多个节点对同一件事达成一致。
8.1 2PL 分布式事务,两阶段提交。【强一致性,性能弱,不符合A,有节点掉线则Block等】
8.2 共识算法,底层逻辑都是选举,一般采用广播+版本号确定主节点,然后采用主从复制来实现全局线性一致性。选举算法超过一半投票即生效,以保证可用性,不依赖全部节点
8.3 共识算法适合少数机器构成分布式协调系统【zookeeper,etcd等】
8.4 raft 分为两阶段,广播选举leader,leader作为主几点保证全局线性一致。每次提议,需要大于半数以上的节点同意,保证高可用性达成。所有节点随机的超时时间收不到心跳则发起竞选流程,每次竞选后递增epochnum,防止脑裂后旧的主节点误以为自己还是主节点。
三、派生数据系统
1. 批处理
unix管道处理思想,map+reduce。
map和reduce之间,多个批处理任务之间,通过hdfs文件做衔接接口。每一步都落hdfs盘。hdfs多副本提供给高可用性。
慢:每一步都要等待前一步完全完成,才能从hdfs文件开始新的一步。
容错:每一步都可以从hdfs临时文件重新拉起进行重试。
2. 流处理
无界数据的处理。算子之间直接衔接。
统计:时间窗口统计处理。
事件流发送系统:
消息系统的实现方式:1. 消息代理【JMS标准/AMQP标准】,负载均衡式/扇出式。系统中可以综合两种方式实现灵活的数据流的处理。
消费后删除【确认消费有副作用】
2. 分区日志:
通过偏移量记录订阅进度,客户端可以反复订阅。
3. 消息系统:
AMQ类型的处理,consumer消费消息后,producer会删除。所以有确认机制。
at-most-once:consumer处理提交前发送确认,如果发送确认后崩溃,下次不会在有消费处理
at-least-once: consumer处理提交后发送确认,如果提交后还没发送确认崩溃,则重启后还会在消费一次。
exactly-once: 和分布式系统遇到的问题一样,producer和consumer必须就每一次消费达成一致,可以使用两阶段提交来达成。
四、 hadoop架构
hdfs+mapreduce+yarn
五、Hbase
基于hdfs,存储结构采用lsm。顺序写,写性能比较高,读性能比较差。
附录:
服务器主频一般3.8GHZ【每秒3.8G次】
深度:
关联搜索,小型流式计算,为了极致性能,将kv数据的分片存储和计算节点放在同一台物理机上,qps30万以上。500万的数据,10台机器,2秒以内就可以完成。es hack 返回整个倒排。流式分发统计,小型mr。
meta数据的同步,计算阶段状态的同步,ssession的保存,程序内部也是启动不同的task,负责分发的,负责接收的,负责统计的。
时间比较紧的情况下,简化设计,无中心化,谁收到请求,谁就作为master,向其他机器分发任务。 之所以没有复杂化,第一探索阶段摸坑,第二oltp系统,尽量简化流程。
react 模型,程序内部的,spring的bean初始化的过程中,consumer 注册自己到一个队列queue,producer生产完之后,使用queue.active(event)来激活对event的各种处理,好处是,架构上分离了consumer,独立化,切可以多种组合。最终还是在一个线程中执行。
epool,事件通知机制,内核信号量等通知机制,一直挂起等待,有事件时收到通知去处理。
消息队列,kafka/mq。
轮询机制,某些场景下可以使用,简化整体架构对外部消息组件的依赖
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本