第一章 可靠,可扩展,可维护的应用系统
可靠性
可靠性可以理解为即使发生某种错误,系统仍然可以正常运行。
我们不可避免会面对故障出现。面对故障,怎么才能设计容错机制避免故障才是根本关键。
硬件错误
硬件错误指的是硬件出现故障。这种错误可以通过硬件升级来解决。通过软件容错的方式也可以容忍硬件错误。
软件错误
软件错误指的系统内的软件出错导致系统出现问题。
软件错误往往比硬件错误更加致命,因为一台硬件出错,往往不会影响到另外的硬件。但是软件出现错误可能会导致一系列的错误,比如一个服务依赖于另外一个服务。
可扩展性
可扩展性是系统应对负载增加的能力的性质。
负载
一个系统要应对增加的负载。系统的设计会比较重要。对于负载的描述很重要,比如每秒请求多少次。
性能
描述负载后就要考虑性能和资源。
比如:负载增加后,资源不变,性能会下降多少。负载增加后,想要性能不变,要增加多少资源。
延迟和响应时间是描述性能的一种方式。延迟指的是处理请求的时间,响应时间指的是处理请求的时间,再加上传递的时候网络拥塞等问题导致的时间延长。
应对负载增加的方法
如果业务正处在快速增长期,那么需要针对每一个数量级都做出负载增加的预案。
垂直扩展:增加机器的性能
水平扩展:将负载分配到更多机器上
可维护性
可维护性可以分成三个方向:可运维性,简单性,可演化性
可运维性:提供检测系统健康状况的机制,可以追踪问题的原因....
简单性:设计好的抽象,对外提供简洁的接口,代码内部耦合度低...
可演化性:一套系统由多个服务配合形成。如何分解这些服务,从而保证当业务需求变化的时候可以简洁地进行演化。
第二章 数据模型与查询语言
关系模型与文档模型
SQL是最著名的关系模型。数据被组织成关系,在SQL中称为表。表由元组的无序集合组成,称为行。
对象-关系不匹配
对象指的是代码里的对象,关系指的是数据库的关系。通常ORM框架可以解决很大程度的对象关系不匹配的问题。
对于一对多的关系,通常有以下三个方式来处理。
1. 建立多个表,构建外键引用的关系
2. 使用json/xml编码存储在单行内
3. 编码成json文档,把文档存储在行内
json比以往的多个表的优势在于,关系模型中读取多个表,会有复杂的连结关系还可能存在多次查询的问题,而存储json只需要查询一次即可。
多对一与多对多的关系
存储ID还是存储字符串?
一个典型的例子,某个人的家乡信息存储的是ID还是字符串呢?
优秀的设计应该是设计成字符串格式。
字符串是对人类有意义的,可能存在重复的情况,但是ID不会
当某个城市的名字发生了变化,如果是字符串,就要修改所有表中的字符串,但是如果是ID,则不需要变更,只需要修改ID对应的字符串解释就可以。
本地化支持更好。存储的如果是字符串,那么国际化之后,要考虑字符串语言转换的问题,但是ID不存在这个问题。
文档数据库的比较
在一对多的关系中,关系型数据库和文档数据库存在差异。关系型数据库记录外键,而文档型数据库是在父记录中存储了嵌套记录。
在多对一和多对多中,没有差别。关系型数据库存储外键,文档数据库存储文档引用。
关系数据库和文档数据库现状
文档数据库的模式灵活,局部灵活性更好。
关系型数据库对于多对一和多对多的关系表达更简洁
哪种模型的代码更简洁
取决于数据模型
如果存在很多一对多的数据模型,那么文档数据更优秀。因为关系型数据库会拆分出很多的表。
如果存在很多多对多或者多对一的模型,那么关系型数据库显然更好。
文档模式中的灵活性
因为文档模式中的json,它更加灵活
举个例子,如果需要添加某个字段。只需要在转化json的过程中进行判断。
但是如果是关系型数据库,就需要怎加一个列,这个alter的过程耗费时间很长。
如果数据大多数情况下不具有相同的结构,那么最好选择文档模式。
如果数据大多数结构都是相同的,那么最好选择关系型模式。
查询的数据局部性
对于大文档来说,查询具有优势。对于关系数据库来说,查询大文档的时候可能会进行多次查询操作。
但是对于修改来说,文档模式就会有一定的劣势。在修改的时候会对整个文档进行重写。这也限制了文档数据库的应用场景。
文档数据库和关系数据库的结合
现在很多关系数据库都支持对xml和json的支持。这可以结合关系数据库和文档数据库的优势。
数据查询语言