在谈及后端架构的时候,很多人的第一反应都是Spring Boot或SpringMVC这些框架。在这之上,可能会想到使用数据库、Redis、第三方应用调用等。也就是说,在很多人的认知里,后端应用程序就是在使用现成框架的基础上,用代码整合数据库、Redis和第三方应用等的胶水程序。
在这样的认知上,编写后端程序就会变成一件“根据每个接口的功能黏合数据库等工具”的事情,也就是说,“使用工具”变成了目的,而不是解决问题的手段。再者,由于人的天然惰性和工具本身的复杂性,开发人员会把工具的使用方式不断简化,最后会出现很多性能上或功能上的问题。这些问题很琐碎,如果在开发阶段不避免这些问题,那么网站的优化工作量会变得十分巨大,并且优化进度将变得不可控。这大概就是开发团队每天都加班加点地工作,但是问题却源源不断出现的原因。
以使用数据库为例,使用方式不断简化后,最后可能只剩下对数据单纯地进行“增、删、改、查”操作。当某接口需要对某个数据进行加1操作时,往往会先把数据取出来,再把数据加1后的结果存回数据库,这样做不仅会浪费数据库性能,而且在并发请求时会发生问题。其实,数据库本身支持对某个数据的加减操作,而且可以避免并发操作产生的问题。这些操作方式一旦出现,一般会像传染病一样扩散,因为在大多数开发者的眼里,能使用工具完成某个功能就可以了,不需要关心可能会存在哪些问题。
事实上,后端架构并不是简单地选用Spring Boot等框架,也不是片面地决定使用哪些工具。“使用工具”只是解决具体问题的手段而不是目的。再者,后端应用程序不是数据库等工具的胶水程序,它并不是单纯的协调者,它是这些工具的使用者,是为了实现某项功能而使用这些工具。
因此,后端架构更应该关心后端应用程序需要解决的问题,而不是选择工具或者使用工具的方法。后端架构一般需要解决4个问题来提高后端应用程序的质量和性能,分别是规整化、数据库、非关系型数据库和整合其他应用程序。
后端应用程序一般都会使用框架,使用框架能减少很大一部分工作量,如接口路由、请求参数注入及返回参数转换等。但是,框架本身是不能保证后端应用程序的质量的,这是因为框架解决的都是一些共通的问题,而决定软件质量的关键往往是一些具体细节。
但是,后端应用程序的很多细节一般都是不被关注的。这是因为后端应用程序可以看作一个个接口的集合,接口与接口之间一般被认为是天然解耦、互不影响的,而且每个接口需要处理的事情不会太多(大多都是对数据的“增、删、改、查”操作),每个接口的代码量自然也不会太多,因此后端应用程序的混乱会被控制在一定范围内。
事实上,接口与接口之间不是互不影响的,混乱也不会被控制在一定范围内。接口之间可能会调用一些公共函数,而函数的调用关系一般都是“九曲十八弯”的,如图4.36所示。
如果大型网站系统的后端架构不关心这些编码细节的话,那么后端应用程序会变得非常混乱。这种混乱会直接造成成本浪费,因为开发人员需要花很多时间去梳理旧代码的同时,很难避免对旧功能产生影响。更可怕的是,这种混乱会随着网站的更新与迭代不断加剧,从而使网站系统的更新变得举步维艰。
综上所述,后端架构应该关注一些具体细节,制定一些规则来约束整个开发过程,从而避免由于代码过度混乱造成的成本浪费。
数据库基本上是每个网站系统的“标配”,这是因为网站系统需要在服务器端集中处理数据,而数据库是专门进行数据存储和数据处理的软件。需要注意的是,数据库本身是一个独立的软件,后端应用程序和数据库是相互独立的两个部分。
说明:这里的数据库指的是关系型数据库,指采用了关系模型来组织数据的数据库,以行和列的形式存储数据。比较流行的关系型数据库有MySQL、Oracle和Microsoft SQL Server。
一个网站系统尤其是大型网站系统,每时每刻都需要处理海量的数据,因此数据库的“压力”往往是最大的。数据库的承载能力很大程度上决定了网站系统的并发能力(同时在线用户量)。
说到数据库的承载能力,很多人的第一反应是数据库选型、表设计、数据库服务器硬件性能及数据库配置等。这些当然会提高数据库承载能力的上限,但是只提高上限是不够的,操作数据库的时候还需要尽量优化数据库的性能。
在一个网站系统中,操作数据库的软件主要是后端应用程序,因此后端架构需要关心和约束其操作数据库的细节,以达到尽量优化数据库性能的目的。
理论上,关系型数据库能满足所有的业务需求,不过网站系统仅仅使用关系型数据库的话会有3个问题:
·在关系型数据库操作中,最多的是查询操作。对于查询操作而言,相同请求在一段时间内查询的结果其实都是相同的,而数据库基本上每次都要重新检索一次,这无疑是需要优化的点。
·在关系型数据库操作中,更新是非常损耗性能的,在某些业务场景(如点击量更新等)中需要频繁更新数据,对于这些业务场景,需要想办法减轻数据更新的频率。
·关系型数据库由于其表格形式的限定,在某些业务场景中的表现是乏力的。例如,针对社交关系等关系复杂的数据。
使用非关系型数据库能有效缓解上述3个问题。需要注意的是,非关系型数据库不是指某一种数据库,而是一类数据库的总称。非关系型数据库一般包括Redis等键值存储非关系型数据库、HBase等列存储非关系型数据库、MongoDB等文档型非关系型数据库、Neo4J等图形非关系型数据库。
说明:非关系型数据库一般也被称为NoSQL。NoSQL的说法是相对于使用SQL语言作为交互的关系型数据库而言的。
针对问题一,虽然关系型数据库也有自己的缓存机制以达到减少检索的目的,但是其起到的效果有限。而引用Redis等键值存储非关系型数据库可以对预期访问量大并且更新概率较小的数据进行缓存,这样可以大大减小关系型数据库的压力,如图4.37所示。
针对问题二,可以引用Redis等键值存储非关系型数据库作为数据中转站,更新数据时不直接更新数据库中的数据,只更新Redis等键值存储非关系型数据库中的数据,一段时间后,再把数据更新到数据库中,如图4.38所示。这是因为Redis等键值存储非关系型数据库是内存级操作,其更新所损耗的性能是相对较小的。
针对问题三,应对海量数据时,采用HBase等列存储非关系型数据库比较省力;应对大量不能限制结构的数据时,采用MongoDB等文档型非关系型数据库比较省力;应对社交关系等关系复杂的数据时,采用Neo4J等图形非关系型数据库比较省力,需要注意的是,这里的图形不是图片,是图形结构的意思。综上所述,后端架构需要根据特定的数据检索压力、数据更新压力和特定的业务场景,选用特定的非关系型数据库,以达到减轻数据库压力和合理使用数据库的目的。
前面只解决了怎么较好地管理大量数据这一个问题,而大型网站系统往往需要提供一些比较复杂的功能,如发送短信、视频转码、全文搜索等。因此后端架构需要考虑如何整合其他应用这一问题。这些应用程序大概可以分成3种:
·第三方平台提供的服务,如直播服务、短信服务等。
·需要本地部署的应用软件,如Solr全文搜索软件等。其实数据库也算是这种类型。
·自主开发的云计算服务,如特定的爬虫软件、支持在线编辑视频的引擎等。
在整个网站系统架构中,后端应用程序类似一个“中央调度”的角色。它的每个接口都是轻量的,不会有太复杂的逻辑或算法,但是它可以作为其他应用程序的“指挥中心”。后端应用程序可以通过对其他独立应用程序的调度,达到为网站系统提供复杂功能的目的,如图4.39所示。