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

本文主要是介绍《数据密集型应用系统设计》笔记——第一部分 数据系统基础(ch1-4),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

写在前面:对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编程模型集成到单个框架中
        • 仍需担心向前和向后兼容性问题(滚动升级),因为消息可能会从运行新版本的节点发送到运行旧版本的节点

这篇关于《数据密集型应用系统设计》笔记——第一部分 数据系统基础(ch1-4)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/934502

相关文章

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

关于数据埋点,你需要了解这些基本知识

产品汪每天都在和数据打交道,你知道数据来自哪里吗? 移动app端内的用户行为数据大多来自埋点,了解一些埋点知识,能和数据分析师、技术侃大山,参与到前期的数据采集,更重要是让最终的埋点数据能为我所用,否则可怜巴巴等上几个月是常有的事。   埋点类型 根据埋点方式,可以区分为: 手动埋点半自动埋点全自动埋点 秉承“任何事物都有两面性”的道理:自动程度高的,能解决通用统计,便于统一化管理,但个性化定

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

基于人工智能的图像分类系统

目录 引言项目背景环境准备 硬件要求软件安装与配置系统设计 系统架构关键技术代码示例 数据预处理模型训练模型预测应用场景结论 1. 引言 图像分类是计算机视觉中的一个重要任务,目标是自动识别图像中的对象类别。通过卷积神经网络(CNN)等深度学习技术,我们可以构建高效的图像分类系统,广泛应用于自动驾驶、医疗影像诊断、监控分析等领域。本文将介绍如何构建一个基于人工智能的图像分类系统,包括环境

水位雨量在线监测系统概述及应用介绍

在当今社会,随着科技的飞速发展,各种智能监测系统已成为保障公共安全、促进资源管理和环境保护的重要工具。其中,水位雨量在线监测系统作为自然灾害预警、水资源管理及水利工程运行的关键技术,其重要性不言而喻。 一、水位雨量在线监测系统的基本原理 水位雨量在线监测系统主要由数据采集单元、数据传输网络、数据处理中心及用户终端四大部分构成,形成了一个完整的闭环系统。 数据采集单元:这是系统的“眼睛”,

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

异构存储(冷热数据分离)

异构存储主要解决不同的数据,存储在不同类型的硬盘中,达到最佳性能的问题。 异构存储Shell操作 (1)查看当前有哪些存储策略可以用 [lytfly@hadoop102 hadoop-3.1.4]$ hdfs storagepolicies -listPolicies (2)为指定路径(数据存储目录)设置指定的存储策略 hdfs storagepolicies -setStoragePo

Hadoop集群数据均衡之磁盘间数据均衡

生产环境,由于硬盘空间不足,往往需要增加一块硬盘。刚加载的硬盘没有数据时,可以执行磁盘数据均衡命令。(Hadoop3.x新特性) plan后面带的节点的名字必须是已经存在的,并且是需要均衡的节点。 如果节点不存在,会报如下错误: 如果节点只有一个硬盘的话,不会创建均衡计划: (1)生成均衡计划 hdfs diskbalancer -plan hadoop102 (2)执行均衡计划 hd