《数据密集型应用系统设计》笔记——第一部分 数据系统基础(ch1-4)

news2024/12/30 1:29:08

写在前面:对DDIA这本书慕名已久,粗看书里的一些知识都或多或少了解,但仔细阅读下来,还是缺少对细节的认识。目前看了四个章节,这本书一直在围绕两个问题:是什么和为什么,来做阐述,针对工业界已有的技术和存在的问题分析的非常细致,让我时常有种恍然大悟的感觉,对各种知识之间的关联讲述的非常到位。所以写下每章要点的笔记,时常回顾时常新

第1章 可靠、可扩展与可维护的应用系统

Redis既可以用于数据存储也适用于消息队列,Apache Kafka作为消息队列也具备了持久化存储保证
需要将任务分解,每个组件负责高效完成其中一部分,多个组件依靠应用层代码驱动有机衔接起来。
关注对大多数软件系统都极为重要的三个问题: 可靠性、可扩展性、可维护性

  • 可靠性
    • 容错总是指特定类型的故障
    • 通过随机杀死某个进程,这种故意引发故障的方式,来持续检验、测试系统的容错机制
    • 硬件故障:硬件冗余方案、软件容错(当需要重启计算机时为操作系统打安全补丁,可以每次给一个节点打补丁然后重启,而不需要同时下线整个系统(即滚动升级))
    • 软件错误:节点之间是由软件关联的,因而往往会导致更多的系统故障。认真检查依赖的假设条件与系统之间交互
    • 人为失误:抽象层、沙箱、测试、快速恢复、监控子系统、管理培训
  • 可扩展性
    • 系统应对负载增加的能力
    • 什么是负载?QPS、数据库写入比例、聊天室的同时活动用户数量、缓存命中率。具体系统瓶颈取决于平均值,或者峰值
    • TP50、TP99、TP999:满足百分之**的网络请求得到响应所需要的最低耗时值是多少
    • 考虑每增加一个数量级的负载,架构应如何设计
    • 如何在垂直扩展(即升级到更强大的机器)和水平扩展(即将负载分布到多个更小的机器)之间做取舍
    • 把无状态服务分布然后扩展至多台机器相对比较容易,而有状态服务从单个节点扩展到分布式多机环境的复杂性会大大增加
  • 可维护性
    • 可运维性、简单性、可演化性
    • 抽象、可操作性

第2章 数据模型与查询语言

每层都通过提供一个简洁的数据模型来隐藏下层的复杂性

  • 关系模型与文档模型
    • SQL:数据被组织成关系,在SQL中称为表,其中每个关系都是元组的无序集合
    • 关系模型的目标就是将实现细节隐藏在更简洁的接口后面。
    • NoSQL:不仅仅是SQL,支持超大数据集,支持一些特定的查询操作,混合持久化。
    • 对象-关系映射(ORM):应用层中的对象与数据库模型之间的转换层。模型之间的脱离有时称为阻抗失谐
    • 使用ID的好处:ID对人类没有意义,ID的具体内容改变不影响其他副本
    • 网络模型:记录之间的链接像指针,访问记录的方法是选择一条始于根记录的路径,沿着链接依次访问。像在一个n维数据空间中进行遍历
    • 关系模型:定义了所有数据的格式:关系(表)只是元组(行)的集合,没有访问路径。解决多对多关系。
    • 文档模型:是某种方式的层次模型,即在其父记录中保存了嵌套记录(一对多关系),而不是存储在单独的表中。多对一和多对多关系与关系模型没区别,相关项由唯一标识符引用:外键或文档引用。
  • 数据查询语言
    • 每个数据模型都有自己的查询语言或框架
    • 声明式查询语言(SQL)很有吸引力,它比命令式API更加简洁和容易使用。但更重要的是,它对外隐藏了数据库引擎的很多实现细节
    • SQL不保证顺序,而数据库无法确定命令式代码是否依赖于排序
    • SQL适合于并行执行,主要通过增加核数。命令式代码由于指定了特定的执行顺序,很难在多核和多台机器上并行化
    • MapReduce:SQL的分布式实现,如MongoDB
  • 图状数据模型
    • image.png
    • 属性图模型:可以将图存储看作由两个关系表组成,一个用于顶点,另一个用于边。图有利于演化:向应用程序添加功能时,图可以容易地扩展以适应数据结构的不断变化
      • Cypher查询语言:用于属性图的声明式查询语言,对于声明式查询语言,查询优化器会自动选择效率最高的执行策略
      • SQL中的图查询:采用递归公用表表达式
    • 三元存储模型:所有信息都以非常简单的三部分形式存储(主体,谓语,客体)。主体相当于图中的顶点,客体是原始数据类型中的value(谓语是key),或图中的另一个顶点(谓语是边)
      • RDF资源描述框架:它让不同网站以一致的格式发布数据,这样来自不同网站的数据自动合并成一个数据网络,一种互联网级别包含所有数据的数据库。三元组的主体、谓语和客体通常是URI。
      • SPARQL是一种采用RDF数据模型的三元存储查询语言。
      • Datalog的数据模型类似于三元存储模式,但更为通用一些。它采用“谓语 (主体,客体) ”的表达方式,而不是三元组

第3章 数据存储与检索

  • 数据库核心:数据结构。简单的做法是用log记录,set方法通过追加实现,get方法则需要O(n)。而索引可以加速读取查询,但每个索引都会减慢写速度(写数据要更新索引)。
    • 哈希索引:哈希表实现
      • image.png
      • 只追加到一个文件,那么如何避免最终用尽磁盘空间?一个好的解决方案是将日志分解成一定大小的段,当文件达到一定大小时就关闭它,并将后续写入到新的段文件中。然后可以在这些段上执行压缩,压缩意味着在日志中丢弃重复的键,并且只保留每个键最近的更新。
      • 每个段现在都有自己的内存哈希表,将键映射到文件的偏移量。为了找到键的值,首先检查最新的段的hash map;如果键不存在,检查第二最新的段,以此类推。由于合并过程可以维持较少的段数量,因此查找通常不需要检查很多hash map。
      • 实现细节:
        • 文件格式:使用二进制格式,以字节为单位记录字符串长度,之后再跟上原始字符串
        • 删除记录:通过墓碑标记,合并日志段时丢失已删除的kv
        • 崩溃恢复:将每个段的hash map的快照存储在磁盘上,可以更快地加载到内存中,以此加快恢复速度
        • 部分写入的记录:通过校验值将损坏部分丢弃
        • 并发控制:一个写线程,多个读线程
      • 追加而不是原地更新:
        • 追加和分段合并是顺序写,比随机写快
        • 在并发和崩溃恢复时要简单,不用担心重写值时发生崩溃
        • 合并旧段可以避免数据文件久而久之出现碎片化
      • 局限:
        • 哈希表必须放入内存,如果key很多会有问题,若放入磁盘,则需要大量的随机访问I/O
        • 区间查询效率不高
    • SSTable排序字符串表:kv按照key排序
      • 合并段更高效:类似合并排序
      • 稀疏地保存所有key的索引
      • 将稀疏索引指向的一个块放入同一个段文件中,并在写磁盘前压缩
      • image.png
      • 既然是排序的key,那就可以通过红黑树或AVL树来维护
      • 写入时添加到内存表(树)中,当内存表大于某个阈值时,将其作为SSTable文件写入磁盘,此时的新数据可以添加到新的内存表中。
      • 读取时先查找内存表中的key,然后是最新的段文件,再是次新,直到找到目标
      • 后台进程执行合并与压缩
      • 问题:如果数据库崩溃,最近的写入(在内存表中但尚未写入磁盘)将会丢失。
      • 解决:在磁盘上保留单独的日志,每个写入都会立即追加到该日志,不需要排序,唯一的目的是崩溃恢复。
    • LSM日志结构合并树:基于合并和压缩排序文件原理的存储引擎,本质就是SSTables
      • 性能优化:
        • 查找某个不存在key:一直访问到最旧的段文件,导致多次磁盘IO,可以使用布隆过滤器解决
        • 大小分级:较新的和较小的SSTables被连续合并到较旧和较大的SSTables
        • 分层压缩:键的范围分裂成多个更小的SSTables, 旧数据被移动到单独的“层级”,这样压缩可以逐步进行并节省磁盘空间
      • 优点:
        • 数据集可以远大于内存
        • 区间查询:key是顺序的
        • 顺序写入:支持非常高的写入吞吐量
    • B-trees:与LSM是将数据库分解成可变大小的段不同,B-tree将数据库分解成固定大小的块或页,一般为4KB
      • 分支因子为500的4 KB页的四级树可以存储高达256 TB
      • 写操作:原地更新覆盖旧页,LSM是追加更新
      • WAL(write-ahead log,预写日志):追加修改,每个B-tree的修改必须先更新WAL然后再修改树本身的页,用于崩溃恢复
      • 并发控制:使用latch(轻量级锁),而LSM则在后台执行合并,用新段原子地替换旧段
      • 优化:
        • 写时复制:修改的页被写入不同的位置,树中父页的新版本被创建,并指向新的位置。而不是使用覆盖页和WAL来进行崩溃恢复
        • 保存key的缩略信息:节省页空间
        • 对树布局,以便相邻子页按顺序保存在磁盘上:减少磁盘IO。而LSM在合并过程中一次重写大量存储段,更容易让连续的key在磁盘上靠近
        • 叶子页面对兄弟页添加额外的指针
        • 变体如分形树:借鉴了一些日志结构的想法来减少磁盘寻道
      • LSM-tree通常对于写入更快,而B-tree被认为对于读取更快。读取通常在LSM-tree上较慢,因为它们必须在不同的压缩阶段检查多个不同的数据结构和SSTable。
      • LSM-tree优点:
        • (写放大):一次数据库写入请求导致的多次磁盘写,如B-tree一次写WAL,一次写树的页本身;LSM-tree由于反复压缩和SSTable的合并,日志结构索引也会重写数据多次。性能瓶颈很可能在于数据库写入磁盘的速率
        • LSM-tree更高的写入吞吐量:因为具有较低的写放大、且顺序写快于随机写
        • LSM-tree支持更好地压缩:定期重写SSTables以消除碎片化
      • LSM-tree缺点:
        • 压缩过程干扰正在进行的读写操作:磁盘并发资源有限
        • 磁盘的有限写入带宽需要在初始写入(记录并刷新内存表到磁盘)和后台运行的压缩线程之间所共享
        • B-tree的优点则是每个键都恰好唯一对应于索引中的某个位置,而日志结构的存储引擎可能在不同的段中具有相同键的多个副本。在许多关系数据库中,事务隔离是通过键范围上的锁来实现的,并且在B-tree索引中,这些锁可以直接定义到树中
    • 内存kv存储:主要用于缓存,通过电池供电的内存、将更改记录写入磁盘、将定期快照写入磁盘、同步内存状态到其他机器
      • 反缓存:当没有足够的内存时,通过将**最近最少使用(LRU)**的数据从内存写到磁盘,并在将来再次被访问时将其加载到内存。
  • 事务处理与分析处理
    • image.png
    • 将数据导入数据仓库的过程称为提取-转换-加载(Extract-Transform-Load, ETL)
    • image.png
    • 使用单独的数据仓库而不是直接查询OLTP系统进行分析,很大的优势在于数据仓库可以针对分析访问模式进行优化
    • 星型模式:当表关系可视化时,事实表位于中间,被一系列维度表包围
    • 雪花模式:其中维度进一步细分为子空间。
  • 列式存储
    • 将每列中的所有值存储在一起,如果每个列存储在一个单独的文件中,查询只需要读取和解析在该查询中使用的那些列,这可以节省大量的工作
    • 列压缩:位图->游程编码
      image.png
    • 列存储排序:指定第一个排序键、第二个排序键···。排序后便于压缩,如游程编码
    • 写操作:LSM-tree
    • 物化视图:缓存查询最常使用的一些计数或总和

第4章 数据编码与演化

  • 数据编码格式
    • 内存中,通常保存在各种数据结构中;文件或网络中,通常编码为自包含的字节序列。从内存到字节序列的转化称为序列化,相反则是反序列化
    • 语言内置编码方案的问题:
      • 编码通常与特定的编程语言绑定在一起
      • 解码过程需要能够实例化任意的类,攻击者可以让应用程序解码任意的字节序列,那么它们可以实例化任意的类,这通常意味着可以远程执行任意代码
      • 经常忽略向前和向后兼容性等问题
      • 次要的效率问题
    • JSON、XML、CSV的问题:
      • 数字编码:精确度、无法区分
      • 不支持二进制字符串
      • 硬编码适当的编解码逻辑
    • Thrift和Protocol Buffers
      • 有相应的代码生成工具,应用程序可以直接调用生成的代码来编解码
      • Thrift:BinaryProtocol、CompactProtocol
      • image.png
      • 向前兼容性:旧代码读取新代码写入的数据,可以忽略不能识别的标记号码(field tag)
      • 向后兼容性:新代码读取旧代码写入的数据,因为标记号码仍然具有相同的含义,在模式的初始部署之后添加的每个字段都必须是可选的或具有默认值
      • PB字段有三种标记:required、optional、repeated,没有列表或数组类型,如图4-4所示,对于重复字段,表示同一个字段标签只是简单地多次出现在记录中
      • Thrift有列表类型,支持嵌套
    • Avro:支持Hadoop
      • 省略,待补,P118
    • 模式(PB、Thrift、Avro)
      • 模式演化,或者理解为版本更新,可以通过字段的field tag来维护
      • 支持更详细的验证规则
  • 数据流模式
    • 当通过网络发送数据或者把它写入文件时,都需要将数据编码为字节序列。
    • 基于数据库的数据流
      • 不同的时间写入不同的值,大多数关系数据库允许进行简单的模式更改,例如添加具有默认值为空的新列,而不重写现有数据,除了MySQL
      • 归档存储,即快照
    • 基于服务的数据流:REST和RPC(其中一个进程通过网络向另一个进程发送请求,并期望尽快得到响应)
      • 客户端和服务端
      • 微服务体系结构:服务器本身可以是另一项服务的客户端(例如,典型的Web应用服务器作为数据库的客户端)。这种方法通常用于将大型应用程序按照功能区域分解为较小的服务,这样当一个服务需要另一个服务的某些功能或数据时,就会向另一个服务发出请求
        • 设计目标:通过使服务可独立部署和演化,让应用程序更易于更改和维护。
      • Web服务:REST(基于HTTP)和SOAP(基于XML)
      • RPC模型试图使向远程网络服务发出请求,看起来与在同一进程中调用编程语言中的函数或方法相同(这种抽象称为位置透明)
        • 网络请求不可预测,如网络问题
        • 可能由于超时无法知道请求是否成功
        • 重复请求:建立重复数据消除(幂等性)机制
        • 时延不同
        • 序列化过程中对于较大的对象可能出现问题
        • 客户端和服务端的语言gap
      • 新一代的RPC框架更加明确了远程请求与本地函数调用不同的事实,gRPC支持流,其中调用不仅包括一个请求和一个响应,还包括一段时间内一系列的请求和响应;支持服务发现
      • REST利于调试,支持所有语言平台,RPC框架主要侧重于同一组织内多项服务之间的请求,通常发生在同一数据中心内
      • 假定所有的服务器都先被更新,其次是所有的客户端。因此,只需要在请求上具有向后兼容性,而在响应上具有向前兼容性
        • Thrift、gRPC、Avro RPC根据自己的编码格式规则进行演化
        • SOAP,请求和响应都基于XML来演化
        • REST使用JSON,添加可选的请求参数、在响应中添加新的字段
    • 基于消息传递的数据流(单向,响应是在独立的通道上完成,是异步的)
      • RPC和数据库之间的异步消息传递系统
      • 消息代理的优点:
        • 充当缓冲区
        • 自动重发,防止丢失
        • 避免发送方知道接收方IP和port
        • 支持发送给多个接收方
        • 将发送方和接收方分离
      • 一个进程向指定的队列或主题发送消息,并且代理确保消息被传递给队列或主题的一个或多个消费者或订阅者。在同一主题上可以有许多生产者和许多消费者
      • Actor模型:用于单个进程中并发的编程模型
        • 每个Actor通常代表一个客户端或实体,它可能具有某些本地状态(不与其他任何Actor共享),并且它通过发送和接收异步消息与其他Actor通信。每个Actor一次只处理一条消息,假定消息可能丢失
        • 分布式Actor框架:用来跨越多个节点来扩展应用程序,实质上是将消息代理和Actor编程模型集成到单个框架中
        • 仍需担心向前和向后兼容性问题(滚动升级),因为消息可能会从运行新版本的节点发送到运行旧版本的节点

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1621961.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AI大模型探索之路-训练篇3:大语言模型全景解读

文章目录 前言一、语言模型发展历程1. 第一阶段:统计语言模型(Statistical Language Model, SLM)2. 第二阶段:神经语言模型(Neural Language Model, NLM)3. 第三阶段:预训练语言模型&#xff08…

【高阶数据结构】B树 {B树的概念;B树的实现:节点设计,查找,插入,遍历,删除;B树的性能分析;B+树和B*树;B树的应用}

一、常见的搜索结构 以上结构适合用于数据量相对不是很大,能够一次性存放在内存中,进行数据查找的场景。如果数据量很大,比如有100G数据,无法一次放进内存中,那就只能放在磁盘上了,如果放在磁盘上&#xff…

Maven多模块快速升级超好用Idea插件-MPVP

功能:多模块maven项目快速升级指定版本插件,并提供预览和相关升级模块日志能力。 可快速进行版本升级,进行部署到Maven仓库。 安装: 可在idea插件中心进行安装 / 下载资源拖动安装 MPVP(Maven) - IntelliJ IDEs Plugin | Marke…

IPv4 NAT(含Cisco配置)

IPv4 NAT(含Cisco配置) IPv4私有空间地址 类RFC 1918 内部地址范围前缀A10.0.0.0 - 10.255.255.25510.0.0.0/8B172.16.0.0 - 172.31.255.255172.16.0.0/12C192.168.0.0 - 192.168.255.255192.168.0.0/16 这些私有地址可在企业或站点内使用&#xff0c…

【第35天】SQL进阶-SQL高级技巧-透视表(SQL 小虚竹)

回城传送–》《100天精通MYSQL从入门到就业》 文章目录 零、前言一、练习题目二、SQL思路初始化数据什么是透视表实战体验 三、总结四、参考 零、前言 今天是学习 SQL 打卡的第 35 天。 ​ 我的学习策略很简单,题海策略 费曼学习法。如果能把这些题都认认真真自己…

网络安全-Diffie Hellman密钥协商

密钥协商是保密通信双方(或更多方)通过公开信道来共同形成密钥的过程。一个密钥协商方案中,密钥的值是某个函数值,其输入量由两个成员(或更多方)来提供。密钥协商的记过是参与协商的双方(或更多…

消息服务应用1——java项目使用websocket

在当前微服务项目中,由于业务模块众多,消息服务的使用场景变得异常活跃。而WebSocket由于其自身的可靠性强,实时性好,带宽占用更小的优势,在实时通讯应用场景中独占鳌头,加上HTML5标准的普及流行&#xff0…

MultiHeadAttention在Tensorflow中的实现原理

前言 通过这篇文章,你可以学习到Tensorflow实现MultiHeadAttention的底层原理。 一、MultiHeadAttention的本质内涵 1.Self_Atention机制 MultiHeadAttention是Self_Atention的多头堆嵌,有必要对Self_Atention机制进行一次深入浅出的理解,这…

Docker 入门篇(一)-- 简介与安装教程(Windows和Linux)

一、Docker简介 Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何Linux机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间没有任何接口(类似iPhon…

记录海豚调度器删除工作流实例失败的解决办法(DolphinScheduler的WebUI删除失败)

本博客记录以下问题解决办法:使用dolphinscheduler的WebUI运行工作流后出现内存占用过高导致的任务阻塞问题,并且在删除工作流实例时总是报错无法删除 解决步骤 在前端页面无法删除,于是搜索资料,发现可以登录数据库进行工作流实…

【C语言 |预处理指令】预处理指令详解(包括编译与链接)

目录 一、编译与链接 1.翻译环境 -预处理 -编译 -汇编 -链接 2.执行环境 二、预定义符号 三、#define定义常量 四、#define定义宏 五、带有副作用的宏参数 六、宏替换的规则 七、 宏函数的对比 八、#和## 1.#运算符 2.##运算符 九、命名约定 十、#undef 十一、 命…

【服务器部署篇】Linux下Tomcat安装和配置

作者介绍:本人笔名姑苏老陈,从事JAVA开发工作十多年了,带过刚毕业的实习生,也带过技术团队。最近有个朋友的表弟,马上要大学毕业了,想从事JAVA开发工作,但不知道从何处入手。于是,产…

Linux网络编程---Socket编程

一、网络套接字 一个文件描述符指向一个套接字(该套接字内部由内核借助两个缓冲区实现。) 在通信过程中,套接字一定是成对出现的 套接字通讯原理示意图: 二、预备知识 1. 网络字节序 内存中的多字节数据相对于内存地址有大端和小端之分 小端法&…

Ubuntu终端常用指令

cat cat 读取文件的内容 1、ls 一、 1、ll 显示当前目录下文件的详细信息,包括读写权限,文件大小,文件生成日期等(若想按照更改的时间先后排序,则需加-t参数,按时间降序(最新修改的时间排在最前)执行: $ ll -t, 按时间升序执行: $ ll -t | tac): ll 2、查看当前所处路径(完整…

Qt中常用对话框

Qt中的对话框(QDialog)是用户交互的重要组件,用于向用户提供特定的信息、请求输入、或进行决策。Qt提供了多种标准对话框以及用于自定义对话框的类。以下将详细介绍几种常用对话框的基本使用、使用技巧以及注意事项,并附带C示例代…

node.js 解析post请求 方法一

前提:依旧以前面发的node.js服务器动态资源处理代码 具体见 http://t.csdnimg.cn/TSNW9为模板,在这基础上进行修改。与动态资源处理代码不同的是,这次的用户信息我们借用表单来实现。post请求解析来获取和展示用户表单填写信息 1》代码难点&…

全彩屏负氧离子监测站的使用

TH-FZ5在繁忙的都市生活中,我们往往忽视了一个至关重要的问题——空气质量。随着工业化的进程加速,空气污染已成为影响人们健康的一大隐患。为了实时监测和了解身边的空气质量,全彩屏负氧离子监测站应运而生,成为了我们守护呼吸健…

企业集成平台建设方案(技术方案+功能设计)

企业集成平台建设方案及重点难点攻坚 基础支撑平台主要承担系统总体架构与各个应用子系统的交互,第三方系统与总体架构的交互。需要满足内部业务在该平台的基础上,实现平台对于子系统的可扩展性。基于以上分析对基础支撑平台,提出了以下要求&…

稀碎从零算法笔记Day59-LeetCode: 感染二叉树需要的总时间

题型:树、图、BFS、DFS 链接:2385. 感染二叉树需要的总时间 - 力扣(LeetCode) 来源:LeetCode 题目描述 给你一棵二叉树的根节点 root ,二叉树中节点的值 互不相同 。另给你一个整数 start 。在第 0 分钟…

25计算机考研院校数据分析 | 北京航空航天大学

北京航空航天大学(Beihang University),简称北航,由中华人民共和国工业和信息化部直属,中央直管副部级建制,位列“双一流”、"211工程”、"985工程”,入选“珠峰计划”、"2011计划”、“111计划”、&qu…