当前位置: 首页 > 科技观察

详谈八种架构设计模式,你知道吗?

时间:2023-03-21 18:00:36 科技观察

1。什么是建筑?我想十个人会用十一个答案来回答这个问题,因为另一个是大家妥协的结果。哈哈,我理解结构就是骨骼,如下图:人体的支撑主要由骨骼承担,其次是其上的肌肉、神经、皮肤。架构之于软件就像骨骼之于人体一样重要。2.什么是设计模式?我问过面试官不下几十次,答案五花八门。在我看来,模式就是经验,设计模式就是设计经验。在使用专项设计、组合设计的情况下,可以大大节省我们的设计时间,提高工作效率。作为一名工作10多年的老码农,经历过不少系统架构设计。接下来,我将在工作中使用到的一些架构设计模式分享给大家,希望大家少走弯路。大体上有八种,分别是:单库单应用模式:最简单,你可能见过内容分发模式:目前用的比较多查询分离模式:针对大并发查询,业务微服务模式:拆多适合复杂业务模型的级缓存模式:可以很好的发挥缓存分库分表模式:解决单机数据库瓶颈弹性伸缩模式:解决业务流量峰谷不均的方法之一Multi-机房模式:解决高可用和高性能的方法3.单数据库和单应用模式这是最简单的设计模式。我们大部分的本科毕业设计和一些小应用基本上都是这种模式。该模式的总体设计如下图所示:如上图所示,该模式一般只有一个数据库,一个业务应用层,一个后台管理系统。所有的业务都是使用业务层来完成的,所有的数据也是存储在一个数据库中,最好能有数据库同步。虽然简单,但也不是没有用。优点:结构简单,开发速度快,实现简单,可用于产品的首版和其他有原型验证需求、用户少的设计。缺点:性能较差,基本没有高可用性,可扩展性差,不适合大规模部署、应用等生产环境。4.内容分发模式基本上所有的大型网站都或多或少地采用了这种设计模式。常见的应用场景是利用CDN技术将网页、图片、CSS、JS等静态资源分发给远程用户。最近的服务器。该模式的总体设计如下图所示:如上图所示,该模式比单数据库单应用模式多了一个CDN和一个云存储OSS(七牛、优拍等类似).一个典型的应用流程(以用户需要上传和查看图片为例)如下:上传时,用户在本机选择一张图片进行上传。程序会将图片上传至云存储OSS,并返回一份图片副本。URL程序将这个URL字符串存入业务数据库,上传完成。查看时,程序从业务数据库中获取图片的URL。程序通过DNS查询该URL的图片服务器。智能DNS会解析该URL,获取离用户最近的服务器(或集群)地址A,然后将服务器A上的图片返回给程序查看。从上面可以看出,这种模式的关键是智能DNS,可以解析离用户最近的服务器。其运行原理大致是:根据请求者的IP获取请求位置B,然后通过计算或配置获取距离B最近或通信时间最短的服务器C,然后将C的IP地址返回给请求者.这种模式的优缺点如下:优点:资源下载速度快,不需要过多的开发和配置,同时也减轻了后端服务器资源的存储压力,减少了带宽占用。缺点:目前OSS和CDN还是有点贵(虽然降价了好几倍),只适合中小型应用。另外,由于网络传输延迟和CDN同步策略,会有一定的一致性。更新缓慢的问题。5.查询分离模式该模式主要解决单机数据库压力过大导致业务变慢甚至超时,查询响应时间变长的问题,同时也包括需要大量计算资源的查询请求数据库服务器。这可以说是单库单应用模式的升级版,也是技术架构迭代演进的必由之路。该模式的总体设计如下图所示:如上图所示,该模式比单库单应用模式和内容分发模式多了几个部分。一是业务数据库的主从分离,二是ES的引入。为什么?想要这样做吗?解决了哪些痛点,下面结合业务需求场景进行详细介绍。场景一:全文关键词检索我想这个需求大多数应用都会满足。如果使用传统的数据库技术,大多会使用likelike的SQL语句。如果再高级一些,可能会先分词,然后把分词索引相关的Record传过去。SQL语句的性能问题和全表扫描机制造成了非常严重的性能问题,现在基本已经很少见了。这里的ES是ElasticSearch的缩写,是一种查询引擎,类似于Solr等,都是类似的技术。ES比Solr配置更简单,使用更方便,所以这里选择它。另外,ES支持横向扩展,理论上不存在性能瓶颈。同时还支持各种插件、自定义分词器等,扩展性强。在这里,使用ES不仅可以代替数据库完成全文检索功能,还可以实现分页、排序、分组、分面等功能。具体要求学生自学。如何使用它?一个大致的过程是这样的:服务器异步的向数据库发送一段业务数据。ES根据规则和配置将记录放入自己的索引库中。客户端查询,此时服务端将这个请求发送给ES,拿到数据后,将数据按照要求进行组装、组合,返回给客户端。实际中如何使用,请同学们根据实际情况进行组合选择。场景二:大量通用查询该场景指的是我们业务中的大部分辅助查询,比如:取款时先查询余额,根据用户ID查询用户的记录,获取最新的取款记录用户资金记录等。我们肯定每天都需要使用它,而且我们经常使用它。同时,我们也有大量的写请求,导致大量的写和查询操作被压到同一个数据库上。然后,数据库挂了,系统挂了,领导生气,被开除,还不起房贷。露宿街头,老婆跟人家跑了,……不敢想,一定要分散数据库的压力。业界比较成熟的方案是数据库的读写分离。写的时候存入主库,读的时候从库读。这样就把压力分散到了不同的数据库上。如果一个数据库读取性能不够好,可以一主多从横向扩展。可谓良药!那怎么用呢?一个大致的过程是这样的:服务端以同步或异步或半同步的方式向数据库发送一段业务数据,读取数据时直接将数据复制到从服务器从库中读取相应的数据比较简单.一些聪明、有思想、有上进心的同学可能会发现问题,包括上面说的第一种场景,就是延迟问题。例如:数据还未从库到达。如果马上读,就会读不下去,就会出问题。对于这个问题,每个公司都有不同的思路和方法来解决这个问题。常见的解决办法是:看不懂就看主库。当然,这也是有前提的,具体的解决方案这里就不一一展开了。我可能会在接下来的分享中详细解释各种解决方案。另外,关于数据库的复制模式,也请同学们自行学习,太多了,这里就不多说了。是时候总结一下这种模式的优缺点了,如下:优点:减轻数据库压力,理论上提供无限高的读性能,间接提升业务(写)性能,专用查询、索引、全文(word细分)解决方案。缺点:数据延迟,数据一致性保证。六、微服务模型上面的模型貌似不错,解决了性能问题。不能再露宿街头了,老婆还是我的,哈哈。然而,软件系统固有的复杂性决定了除了性能之外,还有高可用、健壮性等诸多问题等待着我们去解决。另外,各个部门之间的紧张和扯皮,让我们码农雪上加霜,所以继续嘛……微服务模型可以说是最近的热点了。五颜六色,大大小小的,国内外的企业都在提倡和实践这种模式,但他们中的大多数人都没有弄明白为什么要这样做,也不知道为什么。我不知道这样做有什么好处和坏处。在此,我结合自己的亲身实践,分享一下我对这个模型的看法。不喜欢就不要抱怨!随着业务和人员的增加,遇到了以下问题:单机数据库写请求量明显增加,导致数据库压力增大。一旦数据库宕机,整个业务就会宕机。越来越多的业务代码都在一个GIT中,越来越难维护。代码损坏,味道越来越差侬上线越来越频繁,而且往往是一个小小的功能修改,需要重新编译整个大项目。部门越来越多,大项目哪个部门该改哪个东西,泪流满面。其他外围系统直接相连。数据库,一旦数据库结构发生变化,必须通知所有相关系统,即使是对修改不敏感的系统也必须通知每个应用服务器,所有的权限,网络,FTP,以及其他各种东西都需要打开,因为每个部署的应用由服务器都是一样的。作为架构师,我已经失去了对这个系统的控制权……为了解决以上问题,我们公司采用了微服务模型。这个模型的总体设计如下图所示:如上图所示,我把业务分成块,垂直切分为独立的系统,每个系统独立演化,有自己的库、缓存、ES等辅助系统,系统之间通过RPC进行实时交互,通过MQ进行异步交互,通过这种结合,一起完成整个系统功能。那么,这真的能解决上述问题吗?让我们一一谈谈。对于问题1,因为拆分成多个子系统,分散了系统的压力,每个子系统都有自己的数据库实例,所以数据库的压力变小了。对于问题2,子系统A的数据库宕机,只影响系统A和使用系统A的那些功能,并不是所有的功能都不可用,从而解决一个数据库宕机,所有功能不可用的问题。问题3和4也因为拆分而得到解决。每个子系统都有自己独立的GIT代码库,互不影响。公共模块可以通过库、服务、平台的形式解决。问题5:子系统A发生变化,需要上线。那我只需要编译A就可以上线了。其他系统不需要做同样的事情。问题六:按照康威定律,我们部门应该做什么,输出什么,也会以服务的形式暴露出来。我们部门只需要做好本部门的职责和软件功能即可。问题7、我们部门所有的数据需求都是通过接口发布的。客户通过接口获取数据,从而屏蔽了底层数据库结构,甚至数据源。我们部门只需要保证我们部门的接口契约没有变化即可。是的,新需求增加新接口不会影响旧接口。问题八,不同的子系统需要不同的权限,这个问题也优雅的解决了。问题九:暂时控制复杂度,我只需要控制大的方面,定义系统边界、接口、大流程,然后分而治之,一一分解,纵横结合。目前,所有问题都已解决!答对了!但是随之而来的副作用还有很多,比如RPC、MQ的超高稳定性、超高性能、网络延迟、数据一致性等问题,这里就不展开讨论了。我跟你说吧,太多了,一本书也说不完。另外,对于这款车型来说,最难把握的就是速度了。切记不要分得太细。我见过一个函数一个子系统,几百个方法分到几百个子系统。实在是太多了。在实践中,一个比较可行的方法是:能不区分就别区分,除非有非常必要的理由!优点:性能比较高,扩展性强,可用性高,适用于中型及以上公司架构。缺点:复杂,难以掌握。是指不仅需要一个能够高水平把控大方向、大流程、整体技术的人,还需要能够针对各个子系统进行有针对性的开发。如果不把握度或者滥用,这种模式会适得其反!7、多级缓存模式这种模式可以说是应对超高查询压力的常用策略。基本思路是给所有链接加缓存加缓存即可,如下图:如上图,一般加缓存在三个地方,一个在客户端,一个在API网关,还有另外就是在具体的后端业务,下面会单独介绍。客户端缓存:在这个地方加缓存可以说是效果最好的---没有延迟。因为不需要经过很长的网络链从后端业务获取数据,导致加载时间长,客户流失等损失。虽然有CDN支持,但是从客户端到CDN还是有网络延迟的,虽然不是很大。具体技术取决于不同的客户。对于WEB,有浏览器本地缓存、Cookie、Storage、缓存策略等技术;对于APP,有本地数据库、本地文件、本地内存、进程内缓存支持。.对上述各种技术感兴趣的同学可以继续学习。如果客户端缓存没有命中,那么就会去后端业务获取数据。一般来说都会有一个API网关,这里加个缓存也是很有必要的。在API网关处缓存:在这个地方加缓存的好处是请求不需要发到后面,直接在这里处理,然后返回给请求者。常用的技术,比如http请求,API网关,基本都是nginx。可以使用nginx本身的缓存模块,也可以使用Lua+Redis技术进行自定义。其他一切都几乎相同。后端业务部:这个我想不用我多说了吧。Redis、Memcache、Jvm等大家应该都知道,就不细说了。在实践中,需要结合具体的实际情况,综合利用各级缓存技术,让各种请求在到达后端业务之前得到最大程度的解决,从而减轻后端的压力服务,减少带宽占用,提升用户体验。至于是否只有这三个地方可以加缓存,我觉得还是要灵活学习和使用的。心比剑重要!总结一下这种模式的优缺点:优点:抵抗大量读请求,减轻后端压力。缺点:数据一致性问题比较突出,容易出现雪崩,即如果客户端缓存失效,API网关缓存失效,所有大量请求瞬间压到后端业务系统,而后果可想而知。8、分库分表模式该模式主要解决单表写入、读取、存储压力过大,导致业务缓慢甚至超时、事务失败、容量不足等问题。一般有水平切分和垂直切分两种。这里主要介绍水平切分。这种模式也是技术架构迭代演进过程中的必由之路。这种模式的总体设计如下图所示:如上图红色部分所示,将一个表分成几个不同的库来分担压力。是不是很一般?哈哈,那我们接下来就详细解释一下。先明确几个概念,如下:host:硬件,指物理机,或者虚拟机,有自己的CPU、内存、硬盘等。instance:数据库实例,比如一个MySQL服务进程。一个主机可以有多个实例,不同的实例有不同的进程,监听不同的端口。图书馆:指的是一张表的集合,比如学校图书馆,里面可能有教师表、学生表、食堂表等,这些表都在一个图书馆里。一个实例中可以有多个库。库以库名区分。表:图书馆的表,不用多说,看不懂就别往下看,不解释。那么如何分散单表呢?如何分配?分发到哪里?是计算和存储资源不足造成的,而这些资源主要是由物理机和主机提供的,所以这里的划分是最基本的。毕竟没有可用的计算资源,不管怎么划分,效果都不是很好。实例:实例控制连接数,同时受OS限制,CPU、内存、硬盘、网络IO也会受到间接影响。会出现热实例现象,即:有的实例很忙,有的实例很闲。一个典型的现象是:由于单表响应慢,导致连接池爆满,影响其他所有业务。这时候把表分成不同的实例就有些作用了。数据库:由于单个数据库最大单表数的限制,一般采用分库。表:单表压力太大,索引量大,容量大,单表加锁。根据以上,单表横向划分为不同的表。在大型应用中,一台主机上只有一个实例,一个实例中只有一个库。library==instance==host,所以就有了分库分表的简称。既然你知道了基本理论,那么你是怎么做的呢?逻辑如何运作?接下来,我将举例说明。这个要求很简单。用户表(user)数据量1亿,查询、插入、存储都存在问题。我应该怎么办?先分析问题,很明显是数据量大导致的。其次,设计方案可以划分为10个数据库,使每个数据库的数据量减少到1KW。单表1KW的数据量还是有点大,不利于以后体量的增长,所以每个数据库分成100张表,每个单表的数据量为10W,对于查询、索引更新、单表文件大小、打开速度都有一定的好处。接下来打电话给IT部门,要10台物理机,扩充数据库……最后是逻辑实现,这应该是最有学问的地方了。首先是写入数据。你需要知道写入哪个分库分表。阅读也是如此。因此,需要有一个请求路由层,负责将请求分发和转换到不同的数据库表中。一般都有路由规则的概念。.怎么样,容易吗?哈哈,也是义务。再说说这个模型的问题,主要是因为交易的问题。因为分库分表,无法完成事务,分布式事务过于繁琐,所以这里需要有一定的策略来保证这种情况下的事务。能够完成。采用的策略如:最终一致性、复制、特殊设计等。然后是业务代码的改造,一些关联查询需要改造,一些单表orderBy问题需要特殊处理,包括groupBy语句。如何解决这些副作用,不是一两句话能说清楚的。以后有空再单独说。这些。是时候总结一下这种模式的优缺点了,如下:优点:减轻数据库中单表的压力。缺点:事务保障困难,业务逻辑需要大量修改。9.ElasticSc??alingMode该模式主要解决突发流量的到来导致无法横向扩展或者横向扩展太慢进而影响业务,导致整个站点崩溃的问题。这种模式是比较先进的技术,也是目前各个大公司都在研究和试用的技术。发展到今天,有这种思维的架构师已经很优秀了,可以拿到更高的薪水,更何况是已经实践过甚至实现了底层系统的,所以,你懂的……这种模式的总体设计如下图所示:如上图,增加了弹性伸缩服务,动态增减实例。原理很简单,但是这个模型解决了什么问题呢?先说起源和意义吧。每年双11、6月18日或一些大促之前,我们会针对大流量的到来做以下工作:提前准备10倍以上的机器,即使不用,也要留在那里备用留着吧,以防万一。这浪费了很多资源。每台机器都配置、调试、排空,让所有机器都可用。这样浪费了大量的人力物力,也更容易出错。如果机器没有准备好,那你就得加班加点,重复上面的工作。这样很容易出错,会引起领导的不满。如果你没有时间回家陪老婆,那你老婆就……(我觉得)双十一之后,我们就要手动缩小音量,很辛苦。一般一年会有很多促销活动,所以我们总是这样,真的很烦人!最严重的是突然爆发的大流量会让我们措手不及,半夜起来扩容很正常。于是,我们偷懒了,想要准备更多的机器,大量cpu使用率为1%的机器出现了。相信如果你是老大,一定被震撼到!!!哈哈,那如何改变这种情况呢?请继续阅读。为此,首先将所有计算资源整合到资源池的概念中,然后通过一些策略、监控、服务,动态地从资源池中获取资源,使用后归还资源池,供其他系统使用。实现上比较成熟的两个资源池解决方案是VM和docker,各自都有自己强大的生态。监控点包括CPU、内存、硬盘、网络IO、服务质量等,基于这些,通过一些预留、扩容、缩容策略,可以简单的实现自动伸缩。如何?是不是很神奇?深入的内容我们会在码农原创公众号文章中详细介绍。是时候总结一下这种模式的优缺点了,如下:优点:弹性好,按需计算,充分优化企业计算资源。缺点:应用需要从架构层横向扩展,依赖大量底层配套,对技术水平、实力、应用规模要求高。10、多机房模式该模式主要解决不同地域的高性能和高可用问题。随着应用用户的不断增加,用户群体分布在全球各地。如果服务器部署在一个地方,一个机房,比如北京,那么美国的用户在使用应用的时候会很慢,因为每一个请求都需要经过海底。光缆大约需要一秒钟(估计),这对用户体验来说是极其糟糕的。该怎么办?使用多房间部署。该模式的总体设计如下图所示:如上图所示,一个典型的用户请求流程如下:用户请求一个链接A,通过DNS智能解析到离用户最近的机房B。是不是觉得用B机房的服务链接很简单?,没有什么?其实这里的问题并不像表面上那么简单。让我们一一谈谈。首先是数据同步的问题。中国产生的数据必须同步到美国,美国也是如此。数据同步会涉及到数据版本、一致性、更新丢弃、删除等问题。二是一个地方多个机房的请求路由问题。典型的,如上图,国内的北京机房和杭州机房。如果北京机房宕机了,那么所有发送到北京机房的请求都要通过路由转发到杭州机房。这个问题在其他地方也存在。所以,多机房模式,也就是异地多活动,就没有那么简单了。这只是一个开始。具体的陷阱将在另一篇文章中介绍。是时候总结一下这种模式的优缺点了,如下:优点:高可用、高性能、异地多活。缺点:数据同步、数据一致性、请求路由。至此,八种架构设计模式的整体概述和优缺点介绍完毕,大概1W字。最后想说,世上没有灵丹妙药,灵活运用,共勉!