几种架构设计模式导论(中)

在上篇文章中,主要说了架构设计模式中的两种,既:单库单应用模式、内容分发模式,接下来介绍另外三种架构模式,分别为:查询分离、微服务、多级缓存

1. 查询分离

这种主要解决的痛点是单机数据库压力过大,从而导致业务缓慢甚至超时,查询的响应时间变长的问题,也包括需要大量数据库计算资源的业务查询请求。这个您可以认为是单库单应用模式的升级版本,也是绝大多数公司技术架构迭代演进过程中的必由之路。 这种模式的一般设计见下图:

Paste_Image.png

如上图所示,这种模式较单库单应用与内容分发多了几个部分,一个是业务数据库进行了主从分离,另一个是引入了ES,为什么要这样?都解决了哪些问题,下面具体结合业务需求场景进行叙述。

场景一:全文检索

我想这个业务,大多数应用都会有,如果您使用传统的数据库查询技术,大部分可能都会使用像like这种的SQL语句,高级一一些可能是先分词,后通过分词index相关的记录,弊端是SQL语句的性能与全表扫描机制导致了非常严重的性能问题,现在基本上很少见到。

这里的ES(ElasticSearch),是一种查询引擎,类似的还有Solr等,ES较Solr配置简单、使用起来更方便,所以这里选用了它。另外,ES这种引擎支持横向扩展,理论上没有性能的瓶颈。同时,它还支持各种插件、自定义分词器等,可扩展性非常强。在这里,使用ES不仅可以完全替代数据库完成全文检索功能,还可以实现分页、排序、分组、分面等功能。具体的,请同学们自行学习。那怎么用呢?一般的流程是这样的:

  1. 服务端把一条业务数据落库落表
  2. 服务端异步把该条数据发送到ES
  3. ES把该条记录按照事先写入的规则、配置放入自己的索引库中
  4. 客户端查询的时候,由服务端把这个请求先发送到ES,得到数据后,根据需求进行拼装、组合数据,返回给客户端

实际中具体怎么用,还请同学们根据实际情况酌情做组合、取舍。

场景二:海量的普通查询

普通查询是指我们的业务逻辑中的大部分辅助性的查询,如:取钱的时候必先查询一下余额,根据用户的ID查询用户的相关记录,取得该用户最新的一条取钱记录等。我们肯定是要天天要用的,而且用的还非常多。同时呢,我们的写入请求也是巨多的,导致大量的写入、查询操作压向同一数据库,然后,数据库挂了,系统也挂了,领导必然生气了,你被开除了,还不起房贷了,露宿街头了,你的老婆跟别人跑了,......

不敢想,所以这个就要求我们必须分散数据库的压力,一个业界较成熟的方案就是数据库的读写分离,写的时候入主库,读的时候从从库读。这样就把压力分散到不同的数据库中了,如果一个读库性能不行,扛不住压力的话,可以一主多从,横向扩展。可谓是一剂良药啊!那怎么使用呢?一个一般的流程是这样的:

  1. 服务端把一条业务数据落库
  2. 数据库同步或异步或半同步把该条数据复制到从库
  3. 服务端读数据的时候直接去从库读相应的数据

看起来比较简单吧,一些聪明的、爱思考的、上进的、有老婆的同学可能发现问题了,也包括上面介绍的场景一,就是延迟的问题,如:数据还没有到从库,我就马上读,那么是读不到的,会发生问题的。

对于这个问题,各家公司解决的思路不一样,方法不尽相同。一个普遍的解决方案是:读不到就读主库,当然这么说也是有前提条件的,但具体的方案这里就不一一展开了,我可能会在接下来的分享中详解各种方案。

另外,关于数据库的复制模式,还请同学们自行进行学习,太多了太多了,这里说不清。该总结一下这种模式的优缺点的了,如下:

优点:减少数据库的压力,理论上可以提供无限高的读性能,间接提高业务(写)的性能,专用的查询、索引、全文(分词)解决方案。
缺点:数据的延迟,数据一致性的保证较难。

2. 微服务

上面的模式看似不错,解决了性能问题,我终于可以不用露宿街头了、老婆还是我的,哈哈。但是

软件系统天生的复杂性决定了,除了性能,还有其他例如高可用、健壮性等大量问题等待我们解决,再加上各个部门间的撕逼、扯皮,更让我们码农雪上加霜,所以

继续吧......

微服务可以说是最近的热点,花花绿绿、大大小小、国内国外的公司都在鼓吹,实践这个模式,可是大部分都没有弄清楚为什么要这么做,也并不知道这么做有什么好处、坏处,在这里,我将以我自己的亲身实践说一下我对这个模式的看法。随着业务与人员的增加,遇到了如下的问题:

  1. 单机数据库写请求量大量增加,导致数据库压力变大
  • 数据库一旦挂了,那么整个业务都挂了
  • 业务代码越来越多,都在一个GIT里,越来越难以维护
  • 代码腐化严重、臭味越来越浓
  • 上线越来越频繁,经常是一个小功能的修改,就要整个大项目要重新编译
  • 部门越来越多,该哪个部门改动大项目中的哪个东西,撕逼的厉害
  • 其他一些外围系统直接连接数据库,导致一旦数据库结构发生变化,所有的相关系统都要通知,甚至对修改不敏感的系统也要通知
  • 每个应用服务器需要开通所有的权限、网络、FTP、各种各样的,因为每个服务器部署的应用都是一样的
  • 作为架构师,我已经失去了对这个系统的把控......

为了解决上述问题,我司使用了微服务模式,这种模式的一般设计见下图:

Paste_Image.png

如上图所示,我把业务进行分块,做了垂直切分,切成一个个独立的系统,每个系统各自衍化,有自己的数据库、缓存、ES等辅助系统,系统之间的实时交互通过RPC,异步交互通过MQ,通过这种组合,共同完成整个系统功能。

那么,这么做是否真的解决上述问题了呢?不玩虚的,一个个来说。对于问题一,由于拆分成了多个子系统,系统上的压力被分散了,而各个子系统都有自己的数据库实例,所以数据库的压力变小。

对于问题二,一个子系统A的数据库挂了,只是影响到系统A和使用系统A的那些功能,不会所有的功能不可用,从而解决一个数据库挂了,导致所有功能不可用的问题。

问题三、四,也因为拆分得到了解决,各个子系统有自己独立的GIT代码库,不会相互影响。通用的模块可通过库、服务、平台的形式解决。

问题五,子系统A发生改变,需要上线,那么我只需要编译A,然后上线就可以了,不需要其他系统做同样的事情。

问题六,顺应了康威定律,我部门该干什么事、输出什么,也通过服务的形式暴露出来,我部只管把我部的职责、软件功能做好就可以。

问题七,所有需要我部数据的需求,都通过接口的形式发布出去,客户通过接口获取数据,从而屏蔽了底层数据库结构,甚至数据来源,我部只需保证我部的接口契约没有发生变化即可,新的需求增加新的接口,不会影响老的接口。

问题八,不同的子系统需要不同的权限,这个问题也优雅的解决了。

问题九,暂时控制住了复杂性,我只需控制好大的方面,定义好系统边界、接口、大的流程,然后再分而治之、逐个击破、合纵连横。

目前来说,所有问题得到解决!bingo!

但是,这么做还会有许多其他的副作用会随之产生,如RPC、MQ的超高稳定性、超高性能,网络间的延迟,数据一致性等问题,这里就不展开来讲了,太多了,一本书(厚)都讲不完。

另外,对于这个模式来说,最难把握的应该是度,切记不要切分过细,我见过一个功能一个子系统,上百个方法分成上百个子系统的,真的是太过度了。实践中,一个目前较为可行的方法是:能不分就不分,除非有非常必要的理由!。

优点:相对高性能,可扩展性强,高可用,适合于中等以上规模公司架构。
缺点:复杂、度不好把握。指不仅需要一个能在高层把控大方向、大流程、总体技术的人,还需要针对各个子系统有针对性的开发。把握不好度或者滥用的话,这个模式适得其反!

3.多级缓存

这个模式可以说是应对超高查询压力的一种普遍采用的策略,基本的思想就是在所有链路的地方,尽能加缓存就加缓存,如下图所示:

Paste_Image.png

如上图所示,一般在三个地方加入,一个是客户端处,一个是API网关处,一个是具体的后端业务处,下面分别介绍。

客户端处:这个地方加缓存可以说是效果最好的---无延迟。因为不用经过长长的网络链条去后端业务处获取数据,从而导致加载时间过长,客户流失等损失。虽然有CDN的支持,但是从客户端到CDN还是有网络延迟的,虽然不大。具体的技术依据不同的客户端而定,对于WEB来讲,有浏览器本地缓存、Cookie、Storage、缓存策略等技术;对于APP来讲,有本地数据库、本地文件、本地内存、进程内缓存支持。以上提到的各种技术有兴趣的同学可以继续展开来学习。如果客户端缓存没有命中,那么就会去后端业务拿数据,一般来讲,都会有个API网关,在这里加缓存也是非常有必要的。

API网关处:这个地方加缓存的好处是不用把请求发送到后方,直接在这里就处理了,然后返回给请求者。常见的技术,如http请求,API网关用的基本都是nginx,可以使用nginx本身的缓存模块,也可以使用Lua+Redis技术定制化。其他的也都大同小异。

后端业务处:这个我想就不用多说了,大家应该差不多都知道,什么Redis,Memcache,Jvm内等等,不熬述了。

实践中,要结合具体的实际情况,综合利用各级缓存技术,使得各种请求最大程度的在到达后端业务之前就被解决掉,从而减少后端服务压力、减少占用带宽、增强用户体验。至于是否只有这三个地方加缓存,我觉得要活学活用,心法比剑法重要!总结一下这个模式的优缺点:

优点:抗住大量读请求,减少后端压力。
缺点:数据一致性问题较突出,容易发生雪崩,即:如果客户端缓存失效、API网关缓存失效,那么所有的大量请求瞬间压向后端业务系统,后果可想而知。

本次分享的中篇到此结束,接下来的下篇将介绍最后三种模式:分库分表模式、弹性伸缩模式、多机房模式,相对来讲技术含量更高,敬请期待!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,761评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,953评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,998评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,248评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,130评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,145评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,550评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,236评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,510评论 1 291
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,601评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,376评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,247评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,613评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,911评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,191评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,532评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,739评论 2 335

推荐阅读更多精彩内容