常见的架构模式,战略落地体系
什么是设计模式?
这个问题我问过不下几十个采访对象,答案五花八门。在我看来,模式是经验,设计模式是设计经验。有了这些经验,我们就可以在特定的情况下使用特定的设计和组合设计,这样可以大大节省我们的设计时间,提高工作效率。作为一个工作10多年的老码农,我经历了很多系统架构设计。接下来我会和大家分享一些我工作中用到的架构设计模式,希望大家可以少走弯路。一般来说,有八种,即:
单数据库应用模式:最简单,内容分发模式你们可能都见过:目前我们使用的是多查询分离模式:对于大并发查询和微服务模式:适合复杂业务模式的反汇编和多级缓存模式:缓存可以很好的发挥;子数据库和子表模式;解决单机数据库瓶颈的弹性扩展模式;解决峰谷交通流量不均衡的方法之一;多机房模式;解决高可用性和高性能的方法之一;单数据库和单应用程序模式。
这是最简单的设计模式。我们大部分的本科毕业设计和一些小的申请基本都是这种模式。该模式的总体设计如下图所示:
如上图所示,这种模式一般只有一个数据库,一个业务应用层,一个后台管理系统。所有的业务都是利用业务层完成的,所有的数据都存储在一个数据库里,最好有数据库同步。虽然简单,但也不是没有可取之处。
优点:结构简单,开发速度快,实现简单,可用于第一版产品及其他有原型验证需求,用户少的设计。缺点:性能差,基本没有高可用性,扩展性差,不适合大规模部署、应用等生产环境。内容分发模式基本上,所有大型网站都或多或少采用这种设计模式。常见的应用场景是利用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同步策略的原因,在一致性和更新缓慢方面会出现一些问题。查询分离模式
这种模式主要解决单机数据库压力过大导致业务缓慢甚至超时,查询响应时间变长的问题,还包括需要大量数据库服务器计算资源的查询请求。这可以说是单库单应用模式的升级版,也是技术架构迭代演进过程中的必经之路。通用des
如上图所示,这种模式比单一数据库和单一应用程序模式以及内容分发模式多了几个部分。一是业务数据库的主从分离,二是专家系统的引入。为什么会这样呢?解决了哪些痛点?下面是业务需求场景的详细描述。
场景1:全文关键词搜索
我觉得大部分应用都会有这个要求。如果使用传统的数据库技术,他们中的大多数可能会使用SQL语句,如。高级的可能是先分词,再分索引相关的记录。SQL语句的性能问题和全表扫描机制导致了非常严重的性能问题,现在已经很少见到了。这里的ES是ElasticSearch的缩写,是一种查询引擎,类似于Solr等。都有类似的技术。ES比Solr配置更简单,使用更方便,所以这里选择了它。另外,ES支持横向扩展,理论上不存在性能瓶颈。同时还支持各种插件、自定义分词器等。并具有很强的可扩展性。这里使用ES不仅可以代替数据库完成全文检索功能,还可以实现分页、排序、分组、刻面等功能。具体请自行学习。那怎么用呢?一般流程如下:
将一条业务数据从服务器拖放到数据库中。当服务器将数据异步发送到ESES,并根据规则和配置将记录放入自己的索引数据库客户端进行查询时,服务器将这个请求发送到ES。获取数据后,它根据需求对数据进行组装和组合,并返回给客户端。在实践中如何使用?也请同学们根据实际情况结合选择。
场景2:大量普通查询
这个场景指的是我们业务中的大部分辅助查询,比如取款时先查询余额,根据用户的ID查询用户的记录,获取用户最新的取款记录。我们必须每天使用它,而且我们使用了很多。同时,我们的写请求也非常多,导致大量的写和查询操作压向同一个数据库。然后,数据库挂了,系统挂了,领导生气了,被开除了,还不起房贷,露宿街头,老婆跟别人跑了。
我不敢,所以要求我们分散数据库的压力。业内比较成熟的方案是将数据库的读写分开。写的时候可以掌握数据库,读的时候可以从数据库中读取。这样,压力就分散到了不同的数据库。如果一个图书馆阅读性能不好,不能承受,可以一主多从横向扩展。这是一剂良药!那怎么用呢?一般流程如下:
对于服务器来说,同步、异步或半同步地将一条业务数据下载到数据库中更容易。当服务器从数据库中读取数据时,更容易直接从数据库中读取相应的数据。一些聪明、有思想、有上进心的同学可能会发现问题,包括上面提到的情景1,就是延迟的问题。比如数据还没到数据库,我就马上去读,这样读不出来就有问题了。对于这个问题,不同的公司有不同的思路和方法。常见的解决方法是:不能读主库。当然这是有前提条件的,但具体的解决方法我就不在这里一一展开了。我可能会在下面的分享中详细解释各种解决方案。另外,关于数据库的复制方式,也是要求学生自学的,这里就不多说了。是时候总结一下这种模式的优缺点了,如下:
优点:减轻了数据库的压力,理论上提供了无限的读取性能,间接提高了业务(写)的性能,是查询、索引、全文(分词)的专用解决方案。缺点:数据延迟,数据一致性的保证。微服模式上面的模式看起来不错,解决了性能问题。我不用露宿街头了,老婆还是我的,哈哈。然而,由于软件系统固有的复杂性,除了性能之外,还有许多其他问题有待解决,如高可用性、健壮性等。再加上各个部门之间的扯皮扯皮,让我们的代码耕种雪上加霜,所以
继续.
微服务模式可以说是最近的热点。五彩缤纷,大大小小,国内外的公司都在倡导和实践这种模式,但大多数都不知道为什么要这么做,也不知道这么做的利弊。在这里,我以自己的亲身实践告诉大家我对这种模式的看法。不喜勿喷!随着业务和人员的增加,遇到了以下问题:
单机数据库写请求量大大增加,导致数据库压力更大。一旦数据库挂了,整个业务中挂了越来越多的业务代码,都在一个GIT里。代码越来越难维护,气味越来越浓。上线越来越频繁,往往是一个小功能的修改。越来越多的部门需要重新编译整个大项目。哪个部门改什么在大项目中,其他一些外围系统都是直接连接数据库的,导致一旦数据库结构发生变化,所有相关系统都要通知,甚至那些对修改不敏感的都要通知每个应用服务器,所有权限、网络、FTP、各种应用都需要打开,因为每个服务器部署的应用都是一样的。作为一名建筑师,我已经失去了对这个系统的控制.为解决上述问题,我公司采用了微服务模式。参见该模式的总体设计。
如上图所示,我把业务分成块,纵向分成独立的系统,每个系统都有自己的衍生品,都有自己的辅助系统如库、缓存、es等。系统之间的实时交互通过RPC实现,异步交互通过MQ实现。通过这种组合,整个系统功能共同完成。那么,这样真的能解决以上问题吗?不玩虚的,一个一个来。
对于第一个问题,系统的压力是分散的,因为它被拆分成了几个子系统,每个子系统都有自己的数据库实例,所以数据库的压力变小了。
对于第二个问题,一个子系统A的数据库挂起,只影响系统A和那些使用系统A的功能,不会所有功能不可用,从而解决了一个数据库挂起,导致所有功能不可用的问题。
问题三和问题四,也因为拆分解决了,每个子系统都有自己独立的GIT代码库,不会互相影响。常用模块可以以库、服务、平台的形式解决。
问题5。子系统A发生变化,需要上线。然后我只需要编译一个然后上线就可以了。没有其他系统需要做同样的事情。
第六,遵循康威定律,我们部门应该做什么,输出什么,也是通过服务的形式暴露出来的。我们部门只需要做好我们部门的职责和软件功能就可以了。
七。所有需要我们数据的需求都是通过接口发布的,客户通过接口获取数据,从而屏蔽了底层数据库结构甚至数据源。我们部门只需要保证我们的接口契约没有改变,新的需求会增加新的接口,不会影响旧的接口。
八、不同的子系统需要不同的权限,这个问题已经优雅地解决了。
九、暂时控制复杂度,我只需要控制大的方面,定义系统边界,接口,大流程,然后分而治之,一个一个破,连横结合。
目前来看,所有问题都解决了!答对了。但是也有很多其他的副作用,比如RPC,MQ的超高稳定性,超高性能,网络延迟,数据一致性等等。这里就不说了,因为太多了,写不完一本书。
另外,对于这种模式,最难把握的是度。切记不要分的太细。我见过一个函数一个子系统,几百个方法分成几百个子系统。真的太过分了。在实践中,比较可行的方法是:能分就分,除非有非常必要的理由!
优点:性能相对较高,扩展性强,可用性高,适合中型及以上规模的公司架构。缺点:复杂,难以把握。不仅仅指一个能在顶层掌控大方向、流程、整体技术的人,还包括各个子系统的开发。如果把握不好或者滥用,这种模式会适得其反!多级缓存模式
这种模式可以说是应对高查询压力的常用策略。基本思想是在所有链接中尽可能增加缓存,如下图所示:
如上图所示,缓存一般添加在三个地方,一个是客户端,一个是API网关,一个是具体的后端业务,下面分别介绍。
客户端缓存:这个有缓存的地方可以说是效果最好的——没有延迟。因为从后端业务获取数据不需要经过很长的网络链条,导致加载时间长,客户流失。虽然有CDN支持,但是从客户端到CDN还是有网络延迟,虽然不算大。具体技术取决于不同的客户。对于WEB,有浏览器本地缓存、Cookie、存储、缓存策略等技术。对于APP,有本地数据库、本地文件、本地内存和进程内缓存支持。对上述技术感兴趣的同学可以继续学习。如果客户端缓存没有命中,就会去后端业务获取数据。一般来说会有一个API网关,这里加缓存是非常必要的。
API处缓存:这个地方缓存的好处是不用把请求发送到后方,可以直接在这里处理,然后返回给请求者。常见的技术,比如http请求,API网关基本都用nginx,可以用自己的缓存模块或者Lua Redis技术定制。其他的也差不多。
后端营业厅:这个我觉得不用多说。Redis,Memcache,Jvm等大家应该都知道。所以就不赘述了。
在实践中,需要结合实际情况综合运用各级缓存技术,使各种请求最大程度地在到达后端业务之前得到解决,从而减轻后端服务压力,减少带宽占用,提升用户体验。至于是不是只有这三个地方可以加缓存,我觉得还是要学习,灵活运用。* *心法比剑法更重要!* *总结这种模式的优点和缺点:
优点:抵御大量读取请求,减少后端压力。缺点:数据一致性问题突出,容易出现雪崩。即如果客户端缓存失效,API网关缓存失效,那么所有的海量请求都会瞬间压到后端业务系统,后果可想而知。子数据库子表模式该模式主要解决单个表的写、读、存压力过大,导致业务缓慢甚至超时,交易失败,容量不足等问题。一般有两种分割:水平分割和垂直分割。这里主要介绍水平分割。这种模式也是技术架构迭代演进过程中的必经之路。该模式的总体设计如下图所示:
如上面红色部分所示,一个表被分成几个不同的库来分担压力。是不是很一般?哈哈,接下来详细解释一下。首先,澄清几个概念,如下:
主机:硬件是指自带CPU、内存、硬盘等的物理机或虚拟机。实例:数据库实例,如MySQL服务进程。一个主机可以有多个实例,不同的实例有不同的进程,监听不同的端口。图书馆:指桌子的集合,如学校图书馆,可能包含教师桌、学生桌、食堂桌等。这些桌子在图书馆里。一个实例中可以有多个库。库与库的区别在于库的名称。表格:图书馆里的表格就不用说了。如果你不明白,你不用低头解释。那么如何摊单桌呢?怎么分配?在哪里分发?这里有几个工作中的做法,分享一下:
主持人:这是最重要也是最重要的一点。本质上,子数据库和子表是由于计算和存储资源不足造成的,这些资源主要由物理机和主机提供。所以,在这里是最基本的。毕竟没有可用的计算资源,结果也不是很好。示例:实例控制连接数,并受操作系统的限制。CPU、内存、硬盘、网络IO也间接受到影响。会出现实例热的现象,即有些实例很忙,有些实例很闲。一个典型的现象是由于单个表响应慢导致连接池满,其他所有业务都受到影响。这时候把表分成不同的例子就有些效果了。库:一般由于单个库中单个表的最大数量限制,采用子库。表:单表压力太大,索引大,容量大,单表被锁。按照上面的,把单个表横向分成不同的表。在大规模应用中,一个主机上只有一个实例,一个实例中只有一个库。因此,库实例主机具有子库子表的缩写。
既然知道了基础理论,那怎么做呢?逻辑是如何工作的?接下来举例说明。这个要求很简单。用户表(user)数据量1亿,查询、插入、存储都存在问题。我该怎么办?
先分析问题,很明显是数据太多造成的。其次,设计方案可以分成10个数据库,这样每个数据库的数据量减少到1KW,单个表1KW的数据量还是有点大,不利于以后的增长。所以每个数据库分为100个表,所以每个单表的数据量为10W,有利于查询、索引更新、单表文件大小和打开速度。接下来,打电话给IT部门,要求10台物理机,并扩展数据库.最后,实现逻辑。这应该是最有学问的地方了。第一步是写数据。你需要知道写哪个子数据库子表,读也是一样。因此,您需要一个请求路由层,它负责将请求分发和转换到不同的数据库表。一般来说,你有路由规则的概念。
怎么样,简单?哈哈,太义务了。先说这种模式的问题,主要带来的是交易问题。因为事务由于子数据库和子表而无法完成,分布式事务过于庞大,所以需要有一定的策略来保证这种情况下的事务能够完成。采用的策略包括:最终一致性、复制、特殊设计等。然后就是业务代码的转换,一些关联查询需要转换,单表orderBy的一些问题需要特殊处理,包括groupBy语句。这些副作用怎么解决,不是一两句话能说清楚的。这些我以后有时间再单独说。
是时候总结一下这种模式的优缺点了,如下:
优点:减轻数据库中单表的压力。缺点:交易保障困难,业务逻辑需要大量改造。弹性膨胀模式
这种模式主要解决突发流量到来,导致横向扩展无法或缓慢,进而影响业务和全站崩溃的问题。这种模式是比较先进的技术,也是目前各大公司都在研究和尝试的技术。到今天为止,有这种思维的架构师已经很不错了,可以拿到更高的薪水,更不用说那些已经实践甚至实现了底层系统的人了。所以,你知道.该模式的总体设计如下图所示:
如上图所示,添加了一个弹性伸缩服务来动态增加和减少实例。原理很简单,但是这个模型解决了什么问题呢?先说起源和意义。
每年双11、6月18日或者一些大促到来之前,我们都会为大流量的到来做以下工作:提前准备10倍甚至更多的机器,即使不在使用,也要放在那里以防万一。这就浪费了很多资源。每台机器都经过配置、调试和排水,以便所有机器都可以使用。这样浪费了大量的人力物力,也更容易出错。如果机器没有准备好,你就得加班重复上面的工作。特别容易出错,导致领导不满,也没时间陪老婆回家,然后老婆就.(心想)
双十一过后,我们还要手动收缩容量,很辛苦。一般一年都会有很多促销,所以我们会一直这样。真的很烦!
最严重的是,突然爆发的交通拥堵会让我们措手不及。半夜起来扩张是很正常的。正因如此,我们懒了,想要准备更多的机器,cpu利用率1%的机器大量出现。
我相信如果你是老板你一定很震惊!哈哈,那么如何改变这种情况呢?请继续观看。
所以一开始所有的计算资源都被整合到资源池的概念中,然后通过一些策略、监控、服务从资源池中动态获取资源,用完后再放回池中供其他系统使用。两个比较成熟的资源池方案是VM和docker,各有强大的生态。监控点包括CPU、内存、硬盘、网络IO、服务质量等。根据这些,通过一些预留、扩展和收缩策略,可以简单地实现自动扩展和收缩。最近怎么样?是不是很神奇?
是时候总结一下这种模式的优缺点了,如下:
优点:灵活性,按需计算,全面优化企业计算资源。缺点:应用需要从架构层面进行横向扩展,依赖更多底层设施,对技术水平、实力和应用规模要求较高。多机房模式
这种模式主要解决不同地区的高性能和高可用性问题。
随着应用用户数量的不断增加,用户群体分布在世界各地。如果服务器部署在一个地方,一个机房,比如北京,美国的用户使用应用会非常慢,因为每个请求都需要经过海底光缆一秒钟左右(估计),对用户体验极其不好。我该怎么办?使用多房间部署。
该模式的总体设计如下图所示:
如上图所示,典型的用户请求流程如下:
用户通过DNS请求将链路A智能解析到最近的机房B,并使用机房B为链路A服务
你以为很简单什么都不是吗?其实这里的问题并没有表面那么简单。让我们来看看它们。首先,数据同步的问题。中国产生的数据要同步到美国,美国也是一样。数据同步会涉及到数据版本、一致性、更新丢弃、删除等问题。其次,还有一个地方多个机房的请求路由问题。典型的如上图,中国的北京机房和杭州机房。如果北京机房挂机,所有发送到北京机房的请求都要通过路由转发到杭州机房。这个问题在不同的地方也存在。
所以多机房模式,也就是异地多作业,就没那么简单了。这只是开始。具体的坑会在另一篇文章介绍。
是时候总结一下这种模式的优缺点了,如下:
优点:高可用,高性能,异地多活动。缺点:数据同步,数据一致性,请求路由。至此,八种架构设计模式及其优缺点的整体概述已经介绍完毕,约1W字。最后我想说,没有什么灵丹妙药,灵活运用,互相鼓励!
版权归作者所有:原创作品来自博主小二上九8,转载请联系作者取得转载授权,否则将追究法律责任。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。