本书为什么以数据系统为主题
数据系统是一种模糊的统称,在信息社会中,一切皆可信息化,或者,某种程度上来说--数字化。这些数据的采集、存储和使用,是构成信息社会的基础。
因此作为IT从业人员,有必要系统性地了解一下现代的、分布式地数据系统。学习本书,能够学习到数据系统地背后的原理、了解其常见的实践,进而将其应用到我们工作的系统设计中。
常见的数据系统有哪些?
数据库:存储数据,以便之后再次使用
缓存:记录一些非常重地操作结果,方便之后加快读取速度
搜索引擎:允许用户以各种关键字搜索、以各种条件过滤数据
流式处理:源源不断地产生数据,并发送给其他进程进行处理
批处理:定时处理累积地大量数据
消息队列:进行消息地传送与分发
数据系统的日益复杂化
这些年来,出现了许多新的数据存储工具与数据处理工具,它们针对不同的应用场景进行优化,因此不再适合生硬地归入传统类别。
Kafka:可以持久化存储一段时间日志数据,可以作为消息队列对数据进行分发,可以作为流式处理组件对数据反复蒸馏
Spark:可以对数据进行批处理,也可以化小批为流,对数据进行流式处理
Redis:可以作为缓存加速对数据库的访问,也可以作为事件中心对消息的发布订阅
我们面临一个新的场景,以某种组合使用这些组件的时候,在某种程度上,便是创建了一个新的数据系统。
下图是一个常见的对用户数据进行采集、存储、查询、旁路等操作的数据系统实例,从其示意图中可以看到各种web services的影子。
这样的系统在设计的时候可以有很多取舍:
采用哪种缓存策略,是旁路还是写穿透
部分组件机器出现问题时,是保证可用性还是保证一致性
当机器一时难以恢复,如何保证数据的正确性和完整性
当负载增加时,是增加机器还是提升单机性能
设计对外API时,是力求简洁还是追求强大。
当部分系统降级时,如何为用户提供始终如一的良好性能
因此,有必要从根本上思考下如何评价一个好数据系统,如何构建一个好的数据系统,有哪些可以遵循的设计模式,有哪些通常需要考虑的方面。
用三个词来回答就是:可靠性、可扩展性、可维护性
可靠性
如何衡量可靠性呢?
功能上:
正常情况下,应用行为满足API给出的行为
在用户误输入/误操作时,能够正常处理
性能上:能够在给定硬件和数据量下满足承诺的性能指标
安全上:能够阻止未授权、恶意破坏
如果所有这些在一起意味着“正确工作”,那么可以把可靠性粗略理解为“即使出现问题,也能继续正确工作”。
造成这种错误的原因叫故障,能够预料并应对故障的系统特性可称为“容错”或“韧性”。
注意:故障(fault) 不同于 失效(failure)
故障定义为系统的一部分状态偏离标准
失效是系统作为一个整体停止向用户提供服务。
故障的概率不可能降低到0,因此需要设计容错机制来防止因故障而导致失效。
在这类容错系统里,通过故意触发来提高故障率是有意义的,因为这种方法可以确保容错机制不断运行并接受考验,比如Netflix公司的Chaos Monkey)
硬件故障
在一个大型数据中心中,以下现象是常态:
网络抖动、不通
硬盘老化坏道
内存故障
机器过热导致CPU出问题
机房断电
这些都是硬件故障,磁盘的平均无故障时间约为10-15年,因此从数学期望上来讲,在拥有1w个磁盘的存储集群上,平均每天都会有一个磁盘出故障。
那么如何解决系统的故障率呢? 第一反应通常是增加单个硬件的冗余度,例如磁盘可以组件RAID,服务器可能有双路电源和热插拔CPU,数据中心可能有电池和柴油发电机作为后备电源,某个组件挂掉时冗余组件可以立刻接管。
软件错误
我们通常认为硬件故障是随机的、相互独立的,大量硬件组件之间同时发生故障是极其罕见的。另一类错误是内部的系统性错误,这类错误难以预料,而且是跨节点相关的可能会比硬件故障造成更多的系统失效。
以下列举了几个例子:
不能处理特定输入,导致系统崩溃。
失控进程(如循环未释放资源)耗尽CPU、内存、磁盘空间和网络资源
系统依赖的服务变慢,无响应或是开始返回错误的响应
级联故障
在设计软件时,我们通常有一些环境假设,和一些隐性约束。随着时间的推移、系统的持续运行,如果这些假设不能够继续被满足;如果这些约束被后面维护者增加功能时所破坏;都有可能让一开始正常运行的系统,突然崩溃。
人为错误
系统中最不稳定的是人,因此要在设计层面尽可能消除人对系统影响。根据软件的生命周期,分几个阶段来考虑:
设计编码
尽量消除所有不必要的假设,提供合理的抽象,仔细设计API
进程间进行隔离,对尤其容易出错的模块使用沙箱机制
对服务依赖进行熔断设计
测试阶段
尽可能引入第三方成员测试,将测试平台自动化
单元测试、集成测试、e2e测试、混沌测试
运行阶段
详细的仪表盘、看板
持续自检
报警机制
问题预案
针对组织
- 科学的培训和管理
可靠性有多重要
事关用户数据安全、企业声誉,企业存活和做大的基石