“一学就会,一作就废”微服务的架构模式:一个服务一个数据库模式

无论你喜不喜欢微服务,如今微服务无疑已是程序员们绕不过去的话题了。不管你是想把目前的架构改为微服务,仍是你要出去面试高级一点的岗位,须要深刻理解微服务。程序员

提起微服务,不少程序员对它是又爱又恨,想学微服务不知道如何开始,学了一点以后,又找不到地方去实践。总之就是感受微服务高不可攀,又很难驾驭。面试

首先要明白的是微服务是有套路的,而这些套路基本上解决了微服务结构面临的几乎全部重要问题。数据库

这些套路就是微服务本身的架构模式编程

若是咱们能深刻了解这些模式的其前因后果,就能够理解了微服务绝大部份内容。学习快速,实用价值也极大。服务器

1. 微服务最基本的模式

这篇文章先来说第一个最基本的模式,这个模式我估计须要三篇文章才能讲透,这是上篇。打算中篇写实践,下篇写问题。架构

但愿你们能学的轻松。并发

微服务最基本的模式就是:app

一个服务一个数据库运维

上图就是一个最简单的微服务模式了。分布式

一个服务一个数据库这种模式,是微服务体系结构中的最基础也是最核心的模式。看着简单,可是,这个模式蕴含着微服务的最基本的思想。

要弄清楚一个服务一个数据库这种模式,首先咱们就须要问一下,为何咱们要搞微服务。

2. 传统系统的问题

在谈及微服务的时候,和微服务对应的概念叫作单体系统( Monolithic application )。简单说,微服务是为了解决单体系统的问题才衍生出来的。单体系统结构以下图:

那么这种单体结构出现了什么问题,致使如今你们必须开口闭口微服务了呢?

3. 单体系统太大了

最首要的一个缘由就是应用系统太大。而因为应用系统的过于庞大,若是仅是单体系统的话,就引起了各类各样的问题,体如今如下三个方面:

3.1. 系统自己业务复杂,模块众多

系统随着时间的发展,业务需求愈来愈多。而为了知足这些需求,就致使整个系统的模块愈来愈多。而系统模块愈来愈多,就致使能理解整套系统的人变得愈来愈少,直到最后没有人能够理解整套系统。

3.2. 系统的代码库很是庞大

代码量也会随着系统的增大而增大,代码量的庞大影响了整个开发流程,会致使整个开发成本变得很高。

  • 首先,代码量大,依赖关系复杂,因此对新接手的开发人员来讲,配置开发环境很是耗费精力。
  • 其次,代码量大,加载这些代码和对应的依赖须要的内存就多,因此就会致使开发人员的 IDE 运行很是缓慢,致使编辑代码都很麻烦。
  • 再次,代码量大,若是要把整个代码编译打包,须要的内存也不少,因此也会致使功能开发完成后,对系统的构建会很是缓慢,致使整个构建的时间很是漫长。
  • 再有,代码量大,几乎没人能对总体代码有比较深刻的了解,哪怕可能其中一个要改动的功能,都会由于过于复杂致使开发人员理解不深刻。而这些不深刻的理解又会让开发人员不能使用最佳的方式去作功能开发,从而致使隐藏的 bug。

3.3. 技术团队变得很是庞大

因为功能模块愈来愈多,这就须要愈来愈多的开发人员去开发和维护这套系统。可是,这些开发人员都是面对的同一套代码库,虽然能够搞分支,你们各搞各的。但是一旦须要合代码,发布上线,就是场噩梦。

各类代码冲突,代码丢失,均可能在上线的时候发生。

不只如此,因为顾虑代码丢失和冲突,就须要在上线前,进行足量的测试,而这些测试又须要投入巨大的时间成本。

可是,如今都讲敏捷开发,极可能在还没上线的时候,后续的业务需求又接踵而至,简直要命。

4. 业务需求的个性化

搞微服务,还有一个很重要的缘由是业务需求的个性化和颗粒化。

随着业务的发展,无论是因为市场竞争仍是自己发展的须要,势必须要对自己业务模型的深度挖掘以及提升用户使用系统的各类体验。而基于此类种种,就势必要把系统的各个功能模块作深作透。

这又会引起几个新的问题:

4.1. 系统功能模块可能变得更多更杂

系统功能模块可能被不断拆分红了更细碎的模块,以至可能碎成了颗粒。而因为功能变得更碎更颗粒了,就会让产品经理们更容易的提出一些很是细致的业务需求。

这些很是细致的需求,极可能会形成频繁的功能修改和上线要求。而这些无穷尽的快速需求相对总体庞大的系统上线和开发人员的疲于奔命造成了最激烈的冲突。

4.2. 功能模块对系统的技术要求出现了冲突

好比,不一样的功能模块,订单模块和支付模块。订单模块就但愿系统能尽量的能同时处理大量的订单,甚至能够有必定的容错性,出问题了砍单就能够了。

可是支付模块则不同,支付模块但愿系统能尽可能的稳定,而且必须对准确度要求极高,几乎没有容错的空间。

一样的,在一样的支付模块中(根据系统模块划分而定),可能同时存在本地帐户转帐和三方渠道支付,本地帐户转帐可能须要即时,要求极高的响应时间。可是对于第三方支付,则能够有必定的响应时间容忍度。

若是系统自己是个单体系统,就势必要求开发人员对整套系统作必定的妥协,对冲突的技术需求作出必定的权衡。而这种权衡极可能影响的就是系统总体的体验度。

4.3. 系统模块对服务器的要求出现了冲突

因为功能的深耕细做,则势必会出现性能上的不一样需求。

好比,系统的订单模块,我的下单可能会被频频访问,此时,就须要系统的集群多一些,去处理这些大规模的访问。可是,一样的功能模块里,可能还存在一些企业团购需求,他们没有那么大的访问量,就不须要那么多的服务器集群。

又好比,用户评论截图,可能须要大量的数据存储。可是,一样的,针对用户的个性化推荐就可能须要大规模的密集运算。

除了上面说的,系统庞大引起的问题带来的一些附属问题:

4.4. 故障的连锁反应问题

单体系统从技术上,各个模块是耦合在一块儿的。在实际运行里,极可能就会出现一处故障致使整个系统崩盘的现象。

好比,不经常使用的一个 XX 功能出现了内存泄露,致使整个系统所有不可用了。

4.5. 系统的技术锁死问题

坦白来讲,你得认可在编程里,没有一种语言是完美的,也没有一个数据库是万能的。

好比,Java 作科学计算就没有 Python 那么方便高效。好比,咱们须要存储很复杂的对象关系的时候,MySQL、Oracle 就不如任何一种图形数据库。

因此,系统越复杂,须要不一样技术的几率就越高。可是又因为系统的复杂,引入新技术的风险也就越大。因此,新技术的使用很是困难。

同时,系统庞大后,若是一些组件,甚至语言 SDK 自己的问题若是须要升级,也是一件既繁琐,又充满风险的事情,因此,技术版本升级也很是困难。

综上,对于传统的单体应用来说,系统庞大引起的技术问题,业务发展引起的需求冲突问题……都是没法单凭单体系统的架构思想就能够解决的。

那为何 SOA 也不能解决这些问题呢?

5. SOA 的问题

我们先来看看SOA的结构

能够看到 SOA 架构中有个 ESB(企业服务总线)。这个 ESB 就是专门用于 SOA 的服务和服务之间的互动,是 SOA 必备的基础技术设施。

正由于 SOA 有了服务总线的思想,就注定 SOA 切分的服务不可能太细,由于服务出现的越多,这个服务总线就最终会变成一个总体系统的瓶颈。

SOA 的服务切分规模自己就受到了限制,这个限制就会带来如下的问题:

  1. 切分不够细——咱们说过,咱们的主要问题根源是系统过于庞大,而且还堆在了一块儿。若是咱们切分不够细,那么可能的结果就会变为,从一个很大的系统被切分为了寥寥几个也很大的系统,最终没有解决问题不说,还可能由于系统变成了不一样的分布式服务,又引入了新的分布式系统自己所带来的问题。

  2. ESB 自己就可能成为一个庞大无比的系统怪兽——ESB 做为 SOA 的基础设施,它自己就已经足够复杂,极可能因为业务的发展,它本身也变成了一个恐怖的系统怪物。从而让开发人员不只须要维护原来的系统,极可能还须要为如何维护和修改ESB自己而伤透脑筋。

因此,能够看出来,SOA这种思惟方式和架构实现自己不足以解决庞大单体系统带来的问题。

6. 为何须要服务

回到咱们的微服务的话题。咱们知道了问题的根源,咱们就须要着手解决这些问题。

首先,既然问题是因为系统的庞大复杂引发的,那么咱们就能够参考软件里很广泛的解决思想:分而克之。

不管一个系统有多大,若是咱们将其拆的足够小,就能够把一个复杂的大系统拆分红许多个小系统,再让这分解出来的小系统经过对外提供服务的手段,将他们再聚合成一套大的完总体系,从结果上,就等价为了原来的复杂的大系统了。而这,就是微服务的最朴实的思想。

因此,微服务思想核心有两个:

  • 把系统拆分红不一样的部分
  • 这些部分要足够小

微服务这样作带来了几个好处:

  1. 不管多大多复杂的系统,我只要能拆,会拆,就能把问题简化,从而不用害怕系统变得复杂。

  2. 拆分出来的服务只要足够小,那么不管开发、部署、运维上,都能获得无数原来由于系统庞大而没法得到的好处:修改代码可能变得简单了,测试和运行也变得容易了……

  3. 拆分出来的服务能各自独立发展,不会互相制约。原来系统是单体系统的时候,模块之间因为技术上的耦合,致使没法自由自在的选用最适合当前功能模块的技术,也不能为所欲为的根据当前功能模块的负载状况去弹性的安排服务器。

  4. 故障自然被隔离开了。咱们把系统切分红了服务,每一个服务都有本身的进程或者服务器,这样故障从物理层面就被隔离开了,从而避免了一处不重要的功能故障致使整个系统崩盘。咱们只须要把核心的功能弄的足够健壮,即便非核心功能有了问题,也不会形成太大的损失。

因此,一套巨大的系统,因为自己的臃肿和复杂,就可能会要对其自身进行拆分。而这些拆分,根据一些指导原则,将其拆解的够小,够简单,那么,拆解后带来的效益是很可观的。

7. 为何须要拆库

服务已经拆了,已经得到那么大的好处了。

“可是为何数据库也必需要拆?”——这实际上是不少使用微服务的同窗最疑惑的问题了。

数据库拆分不拆分本质上其实就是数据共享的问题。而一个服务一个库自己的观念,其实就是尽最大程度的避免数据的共享。

数据共享会带来以下几个问题:

7.1. 技术实现依然可能耦合

由于没有拆分数据库,因此,极可能一个原本应该独立出来的服务模块,必须依赖于另外的服务模块,而这和咱们拆分服务的初衷出现了冲突。

好比,订单服务和个性化推荐服务,极可能都须要访问订单相关数据。此时,若是不拆数据库,则极可能因为订单业务需求致使的订单表结构的修改,倒逼个性化推荐服务也要跟着修改。

7.2. 底层数据的过分暴露

仍是上面订单服务和个性化推荐服务的例子,个性化推荐极可能只是须要一些用户 id、订单类别之类的东西,可是因为数据库是共享的,极可能开放的就是订单表的所有数据,而这些数据有不少算是敏感数据,应该被隐藏的,如今则被暴露出去了。

7.3. 无必要的数据访问竞争

由于是同一个数据库,这势必会形成对共享数据的竞争性访问,而这些竞争性访问则会大大影响业务模块的弹性部署。好比,订单模块极可能因为个性化推荐的一些定时批量查询,被影响了其能承载的并发数据量。

因此,看出来了吧,分库是必需要考虑进微服务整个体系结构的。

8. 最后留个尾巴

每个服务对应一个数据库这种模式,是微服务中的最核心最基本的模式,它体现了微服务最核心的思想:

拆分与解耦

通常来讲,微服务大部分时候,都会尽可能采用一个服务一个数据库的模式。

这里只说了为何要使用一个服务一个数据库,而如何去分服务,如何去分数据库,它们是否还存在一些实践上的妥协,这会在下一篇文章里仔细解析。


你好,我是四猿外,一家上市公司的技术总监,管理的技术团队一百余人。

我从一名非计算机专业的毕业生,转行到程序员,一路打拼,一路成长。

我会把本身的成长故事写成文章,把枯燥的技术文章写成故事。

欢迎关注个人公众号:四猿外

相关文章
相关标签/搜索