第一章 可靠,可扩展,可维护的应用系统

可靠性

可靠性可以理解为即使发生某种错误,系统仍然可以正常运行。

我们不可避免会面对故障出现。面对故障,怎么才能设计容错机制避免故障才是根本关键。

硬件错误

硬件错误指的是硬件出现故障。这种错误可以通过硬件升级来解决。通过软件容错的方式也可以容忍硬件错误。

软件错误

软件错误指的系统内的软件出错导致系统出现问题。

软件错误往往比硬件错误更加致命,因为一台硬件出错,往往不会影响到另外的硬件。但是软件出现错误可能会导致一系列的错误,比如一个服务依赖于另外一个服务。

可扩展性

可扩展性是系统应对负载增加的能力的性质。

负载

一个系统要应对增加的负载。系统的设计会比较重要。对于负载的描述很重要,比如每秒请求多少次。

性能

描述负载后就要考虑性能和资源。

比如:负载增加后,资源不变,性能会下降多少。负载增加后,想要性能不变,要增加多少资源。

延迟和响应时间是描述性能的一种方式。延迟指的是处理请求的时间,响应时间指的是处理请求的时间,再加上传递的时候网络拥塞等问题导致的时间延长。

应对负载增加的方法

如果业务正处在快速增长期,那么需要针对每一个数量级都做出负载增加的预案。

垂直扩展:增加机器的性能

水平扩展:将负载分配到更多机器上

可维护性

可维护性可以分成三个方向:可运维性,简单性,可演化性

可运维性:提供检测系统健康状况的机制,可以追踪问题的原因....

简单性:设计好的抽象,对外提供简洁的接口,代码内部耦合度低...

可演化性:一套系统由多个服务配合形成。如何分解这些服务,从而保证当业务需求变化的时候可以简洁地进行演化。


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

关系模型与文档模型

SQL是最著名的关系模型。数据被组织成关系,在SQL中称为表。表由元组的无序集合组成,称为行。

对象-关系不匹配

对象指的是代码里的对象,关系指的是数据库的关系。通常ORM框架可以解决很大程度的对象关系不匹配的问题。
对于一对多的关系,通常有以下三个方式来处理。

1. 建立多个表,构建外键引用的关系

2. 使用json/xml编码存储在单行内

3. 编码成json文档,把文档存储在行内

json比以往的多个表的优势在于,关系模型中读取多个表,会有复杂的连结关系还可能存在多次查询的问题,而存储json只需要查询一次即可。

多对一与多对多的关系

存储ID还是存储字符串?

一个典型的例子,某个人的家乡信息存储的是ID还是字符串呢?

优秀的设计应该是设计成字符串格式。

字符串是对人类有意义的,可能存在重复的情况,但是ID不会

当某个城市的名字发生了变化,如果是字符串,就要修改所有表中的字符串,但是如果是ID,则不需要变更,只需要修改ID对应的字符串解释就可以。

本地化支持更好。存储的如果是字符串,那么国际化之后,要考虑字符串语言转换的问题,但是ID不存在这个问题。

文档数据库的比较

在一对多的关系中,关系型数据库和文档数据库存在差异。关系型数据库记录外键,而文档型数据库是在父记录中存储了嵌套记录。

在多对一和多对多中,没有差别。关系型数据库存储外键,文档数据库存储文档引用。

关系数据库和文档数据库现状

文档数据库的模式灵活,局部灵活性更好。

关系型数据库对于多对一和多对多的关系表达更简洁

哪种模型的代码更简洁

取决于数据模型

如果存在很多一对多的数据模型,那么文档数据更优秀。因为关系型数据库会拆分出很多的表。

如果存在很多多对多或者多对一的模型,那么关系型数据库显然更好。

文档模式中的灵活性

因为文档模式中的json,它更加灵活

举个例子,如果需要添加某个字段。只需要在转化json的过程中进行判断。

但是如果是关系型数据库,就需要怎加一个列,这个alter的过程耗费时间很长。

如果数据大多数情况下不具有相同的结构,那么最好选择文档模式。

如果数据大多数结构都是相同的,那么最好选择关系型模式。

查询的数据局部性

对于大文档来说,查询具有优势。对于关系数据库来说,查询大文档的时候可能会进行多次查询操作。

但是对于修改来说,文档模式就会有一定的劣势。在修改的时候会对整个文档进行重写。这也限制了文档数据库的应用场景。

文档数据库和关系数据库的结合

现在很多关系数据库都支持对xml和json的支持。这可以结合关系数据库和文档数据库的优势。

数据查询语言