原文:Github工程师肖恩戈德克。
程序设计是代码的组装,系统设计是围绕如何组装服务。
程序设计组装的代码是变量、函数、类等,系统设计的组装的是服务器、数据库、缓存、队列、事件总线、代理等。
一个系统如果运行很长时间不出错,它的设计就是良好的。
这个符合中国上医治未病的逻辑,但如果一个缺乏标准的评委,肯定会觉得动作做得多的那个系统是好的。
一个人写出的代码,当别人看到之后,发出:“哇,这比我想要的简单”,它的设计就是优秀的。
好的系统架构是迭代出来的,最开始从一个简单有效的系统发展起来的,千万不要从零开始设计一个复杂的系统。
系统设计的难点在于状态,尽量采用无状态的设计方法,最小化有状态组件的数量。
有状态带来的复杂性在于,你无法通过简单的重启、扩容解决或修复问题,一旦出错,往往需要手动修复状态。
有状态组件最重要的组件是数据库,用它来管理状态,而不要用其他的组件。
数据库的好处,他是结构化的,每张表都易于理解,sql也易于理解,打开一张表,就能了解数据的主要结构和问题原因。
不要讲表结构搞复杂,他是元数据,元数据如果搞复杂就会给系统层面带来巨大的复杂性和扩展约束。
数据库主从复制有延迟,这是常识,要围绕这个常识进行容错设计。
很多人将主从延迟视为问题,出现问题他说是主从延迟引起的,这是没有常识的回答,好的工程师会围绕于这个常识设计方案。
比如更新一条记录后,不是去数据库直接读取它,而是将其放到内存中,从内存中读取。
耗时较高的任务要从在线服务中剥离出来,放到作业系统当中,排队完成。
作业系统主要包含两部分:任务队列组件,作业处理器。
如果数据的生成速度和读取速度不匹配,经典的解法是缓存。
就是将数据保存到分布式缓存中,这样很多系统可以共享这部分缓存。
缓存,它存在的意识就是缓,且易失的,不要把它当成数据库一样的组件管理状态。
除了缓存和后台作业系统,大型系统常用的另一个组件是kafka。
事件中心是一个队列,它存放的是什么时间发生了什么事件,然后事件处理逻辑订阅这个事件,进行处理。
事件中心适用于那些对事件处理时延不敏感的逻辑,它可以削峰填谷,所以适用于事件量大和响应时间不敏感的逻辑。
但不要过度使用事件中心,更简单的方法是让服务之间通过API调用。
数据被多方共享,有推送和拉取两种选择。
一般来说,拉取比较简单(常见的轮训),但推送更节省资源、实时性更好。
但这背后也有不同的性能瓶颈,拉取对数据提供方压力较大,推送对数据消费方压力更大。
更好的方式是采用推拉结合的方式,这个设计好了会很有架构的美感。