读书 | DDIA CHAPTER 1

DDIA:Designing Data-Intensive Applications The Big Ideas Behind Reliable, Scalable, and Maintainable Systems (Martin Kleppmann)
本书将介绍构建数据系统的原则和实例;以及不同的数据工具的共同点、差异性和它们是如何实现这些特点的。

 

目录

前言

关于 Data System

可靠性 Reliability

硬件失效

软件错误

人为错误

可扩展性 Scalability

如何考量负载

 如何考量性能

解决负载增加的办法

可维护性 Maintainability


前言

除了CPU算力,数据密集型、计算密集型的应用面临的更大挑战是:巨量的数据、数据的极端复杂性和迅速变化性。

这些应用通常需要完成以下功能:存储、缓存(记住代价高昂的某些操作的执行结果以便加速运算)、检索 / 筛选、流处理、批处理。

如今貌似每个功能都有现成的优秀引擎可供使用。但是当开发新的应用时,工程师还是需要耐心选择最适合当前任务的工具(比如cache、index都有不同的实现方式,各有优缺点)。此外,总有些问题是单个工具无法完全胜任的,要将不同的工具结合起来也是一个十分棘手的事。

第一章将介绍:搭建一个可靠的、可扩展、易维护的数据系统的基本原则和思维方式。

                           开发系统需要满足功能性需求和非功能性需求(稳定性、可扩展性等)。

                           没有一个简单的公式可以套用。但是有一些模式和技术持续出现在不同的应用中以满足上述需求。

关于 Data System

什么是数据系统:结合了多个不同的数据工具开发的应用。

为什么需要“数据系统”这个名字:一,不同的数据工具之间的边界越来越模糊 二,单一的数据工具越来越难以满足生产需要。

        本来用于存储的Redis也可以用作消息队列;本来是消息队列的Kafka又具有像数据库一样的持久性保证。

什么是一个好的数据系统 / 开发者应关注什么:可靠的、可扩展、易维护

可靠性 Reliability

可靠性的具体要求​​​​​​​

  1. 系统能按照期望的功能运行。
  2. 对客户的误操作有容忍性。
  3. 系统能在期望的运行压力下有符合期待的运行表现。
  4. 阻止无权限的用户访问 / 滥用系统。

failure VS fault

failure是整个系统失效。fault是系统中的部分组件失效。可靠性要求阻止fault导致failure。

prevent VS cure

顾名思义,prevent阻止故障发生,cure是具有故障恢复的能力。cure通常被选择的更多。但有些错误是不存在cure的能力的,比如黑客访问到了安全级别极高的数据、客户账户上的存款被盗走。这些情况prevent是唯一且必须的选择。

延伸阅读:The Netflix Chaos Monkey

硬件失效

硬盘失效、断电、网线插错等等。

常见方案是设置冗余设备:有效但不能完全避免。此外,随着数据量和计算量的增长,按概率来算失效设备数也在增长。对于AWS这些云服务公司,它们并不在乎单台机器的可靠性,系统扩展性和灵活性才是更重要的问题。

通过软件方法解决也是一种途径,优势在于当某个硬件出错时不需要停止整个系统等待新设备备份和上线;在系统升级时也可以在不停机的情况下逐步完成整个系统的更新。

软件错误

软件层面的系统错误包括:操作系统内核bug、进程死锁等。

这类问题往往难以排查且后果比硬件出错更严重。硬件出错往往是互相独立的(除非是环境条件导致大规模失效,比如低温、地震),而软件层面的系统错误则会导致集联问题。

没有一劳永逸 / 简单的方法解决:

严谨的设计、彻底的测试、进程隔离、允许进程终止和重启、实时监控和告警等

人为错误

人为错误导致宕机的比例远高于硬件故障。

可以从以下角度入手规避人为错误:

  1. 严格设置的接口(需要在灵活性之间做一个权衡)
  2. 各个层面上彻底的测试,每个小单元到整个系统。
  3. 设置沙箱实验,real data but not real users
  4. 快速回滚配置和数据的机制,但是逐步更新代码,这样更新后的代码只会对一小部分有影响。(数据也要回滚,因为旧配置在新数据下可能是错误的)
  5. 详细和清晰的监控指标,有助于快速诊断问题。
  6. 良好的员工管理和训练机制。

可扩展性 Scalability

 一个当前稳定的系统在业务量和数据量增长后还能保持稳定需要可扩展性。

扩展性应从多个维度考量。不能说“Y系统是可扩展的” ,说“X系统在Z方面是可扩展的”比较合适。

如何考量负载

不同的业务需求有不同的指标,对不同操作之间的偏向也不同。

以推特为例,考虑到其fanout(扇出?)特性,推特目前的策略结合了消息队列和数据库连表的方式:

        对于粉丝较少的人发布的推文,采用消息队列,用提前成倍写的方式获得更高效的读效率;

        对于粉丝量巨大的名人,采用数据库连表,当有关注该网红的人发起读操作时,从数据库里获得网红发布的推文,按时间顺序插入到其他follower的推文里。

 如何考量性能

  • 两个角度考虑负载增长的代价:负载增加时,如果资源数不变,性能下降了多少;负载增加时,要想维持性能不变,需要增加多少资源?
  • 常见的性能指标:吞吐量(throughput)、响应时间(response time)、延迟(latency)

        区分响应时间(response time)和延迟(latency)

                响应时间 = 系统真正的处理时间(service time​​​​​​​) + 网络延迟时间 + 队列延迟时间

                延迟 = 任务排队等待处理的时间

  • 即使在一个会话里重复执行相同的任务,也会有不同的性能。影响性能的因素有很多:

        a context switch to a background process, the loss of a network packet and TCP retransmission, a garbage collection pause, a page fault forcing a read from disk, mechanical vibrations in the server rack

  • 使用平均值来考量性能不如使用中位数​​​​​​​ / 百分位数​​​​​​​

        分位数高的响应时间 (尾部延迟 tail latencies)直接影响用户体验。

        往往经常体验到最大响应时间的客户是最有价值的(数据量最大,购买的服务最多):AWS 响应时间没增加100ms,销售额就会降低1%。

        当然要提高99%分位数的性能,需要付出的代价是非常昂贵的。

  • 队列延迟是tail latencies的主要原因。队头阻塞(head-of-line blocking)又是队列延迟的的主要原因。
  • 进行扩展性测试的时候,发送请求的间隔和上一个请求的响应时间应互相独立。如果总是等到上一个请求执行结束后才发送下一个请求,相当于人为解决了数据倾斜的问题(skew),测试得到的响应时间会低于实际情况。
  • 监控响应时间的建议:

        最简单的方法:划定时间窗口,将时间窗口内的所有请求的响应时间排序,计算百分位数。

        更高效的近似方法(估计CPU时间,内存占用):forward decay, t-digest , or HdrHistogram

        不要轻易计算平均值,平均值在数学上是没有意义的。​​​​​​​

解决负载增加的办法

  • 纵向扩展(scaling up / vertical scaling) VS  横向扩展(scaling out / horizontal scaling

        横向扩展的一种典型结构:shared-nothing architecture

  • elastic systems :能自动扩展的系统(识别到压力增大时自动增加资源),当负载极度不可预测时需要这种系统。但是相比手动扩展的系统,会更复杂也更容易出现“operational surprises”。
  • 当扩展成本不是太高或可用性要求不高时,不建议将有状态系统从单个节点改变成分布式系统,改造的复杂度代价太大。
  • 目前没有通用的可扩展的系统架构能适用于所有的应用。往某个方向错误的进行扩展最好的结果是浪费资源,最坏的结果是妨碍原有的功能。对于新产品而言快速的在产品功能上迭代比无头苍蝇式的在某个假设的性能上扩展更有效。

可维护性 Maintainability

Operability:降低平时的维护难度

Simplicity:降低新工程师上手的难度

降低复杂度不意味着减少系统功能。而是要追求降低意外复杂度(accidental complexity):

        如果不是系统要解决的问题所固有的复杂度,而是在实现系统的过程中产生的复杂度,被称为accidental complexity。

最好的消除accidental complexity的方法是进行抽象。好的抽象可以被应用到多个不同的应用中、可以隐藏底层的很多细节,向上提供友好的使用界面。(C++里的类、关系型数据库实体关系模型)

Evolvability:降低进行修改时的难度

强烈依赖于Simplicity和抽象。

敏捷联盟:The Agile community

TDD:test-driven development

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
设计数据密集型应用 (DDIA) 是一本由Martin Kleppmann撰写的专业著作,它深入探讨了如何构建高效可扩展的数据系统和应用程序。这本书通过详细解析不同领域的实际案例,帮助读者了解数据密集型应用的核心原则和最佳实践。 在DDIA中,作者首先介绍了数据系统的核心概念,例如数据模型、一致性、可靠性和可扩展性。然后,他详细阐述了各种数据存储和处理技术,包括关系型数据库、NoSQL数据库、消息队列、流处理等等。通过这些技术的比较和分析,读者可以了解它们的优缺点,并为自己的应用选择最合适的工具。 在第二部分,作者讨论了如何设计数据密集型应用的不同组件,包括数据复制和容错、数据分区和分片、数据一致性和并发控制。他提供了一些建议和模式,以帮助读者解决应用中的常见问题,例如数据冲突、性能瓶颈和容量规划。 最后,作者探讨了如何针对不同的应用场景选择合适的数据系统架构,包括关系型数据库、键值存储、文档数据库和图形数据库。他还介绍了流处理和批处理的概念,并介绍了一些实现这些架构的工具和技术。 通过阅读DDIA,读者可以获得设计和构建数据密集型应用所需的全面知识。这本书不仅适合软件工程师和系统架构师,还适用于对数据系统和应用感兴趣的任何技术人员。无论是构建社交网络、大规模数据分析系统还是电子商务网站,DDIA都是一本不可或缺的参考书。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值