考虑系统扩展性时仅仅理解AKF立方体是不够的

图/蒋坤(一位摄影师程序员)

新技术层出不穷,日新月异。几乎每年都有热点,比如去年的区块链,前些年的微服务。

无论再怎么与时俱进总有变与不变的东西。技术在变,有的思想没变。

我们今天就是谈论些思想没有变的东西,也是被一直以来实践检验的。那就是我们考虑系统扩展性的时候,我们是如何思考以及去实施的。

说起如何设计一个系统的可扩展性的时候,一般我们首先需要一套理论来指导,另外还需要一些设计原则和注意事项。

那么AKF立方体无疑是一个比较合适的选择。

第一次看到AKF立方体的说法是在《架构即未来》一书中,第二次看到是在《微服务架构设计模式》这本书中,其实它还有个更早的出处《可扩展的艺术》,当然本文也有对它们的参考。

一、AKF立方体

立方体,就是一个三维的空间,我们要的是 “可扩展”,那么没有比三维的空间更能表达扩展性的了。

AKF立方体是一种理论指导,它可以帮助我们在各个方向上做扩展。X、Y、Z三个方向都给我们指明了道路,让我们在执行的时候可以在不同的方向上做一个参考,参照这一理论来确认我们所做的扩展动作是否符合这一理论。

下图是一个立方体的展示图。

X、Y、Z轴的解读

X轴-横向扩展、水平复制

Z轴-数据分区,比如分库分表

Y轴-功能分解扩展,属于微服务方向

关于AKF更详细的介绍,大家可以查阅其它相关资料。

这里我重点说一点,就是我们在理解AKF立方体的时候,注意一下左下角,也就是上图虚线圆圈的部分。

从这个画圈地方,一个系统相当于初始状态,也是最原始的起点单体,单一实例,有待扩展挖掘的状态。在这种状态下要寻求扩展,就会向三个方向延伸,也就是我们上面介绍的X、Y、Z三个维度。

鉴于我们这篇文章的题目是,当我们聊系统扩展性的时候不仅仅是AKF立方体,接下来我们重点叙述基于这套理论为基础其它的内容。

二、可扩展性、可用性、成本

寻求可扩展性的同时要基于可用性,总不能任性扩展而使系统不可用吧。那么当扩展性和可用性都有了保障的时候,如果忽视了成本,也是要不得。投入产出要有个正比。

这里的成本考虑主要是设计的复杂度,AKF立方体确定了三个维度方向的扩展理论,在每一个维度上,都可深,可浅的进行。

比如横向X轴扩展的时候,我们是否考虑程序设计的是有状态还是无状态等等,因为有状态和无状态的两种设计的成本也是不一样的,接下来我们还会对状态设计详细介绍。

我们在考虑可扩展性的同时一定要将可用性和成本这两个因素也要考虑进来,他们三者的关系需要做一个平衡,如下图所示。

三、设计上的一些原则考虑

1、对异步、同步的考虑

同步的系统调用,比如系统A->系统B->系统C,形成一个同步调用链,这个调用链最大的问题是会发生故障传导。

同步交互的系统,他们的扩展性会受到同步调用链中最慢的那个系统的限制。一旦某个系统或者某个系统的RPC接口变慢,那么调用链靠前的系统都会慢下来,也就是我们上面说的传导。

当访问量增大的时候,一请求一线程的模式下,就会拖慢整个调用方的系统。

但异步调用的系统,对这种“慢”的容忍性会更强。因为如果一旦一个请求依赖变慢,在等待系统响应的同时,可以去处理下一个请求。

虽然响应变慢了,但整个系统并没有变慢。因为能够容忍这种变慢,所以就可以继续处理其它的请求,因此异步调用的系统相当于“实时的进行了动态的扩展”。

我们应当尽可能将系统的通讯模式设计成异步的,这样在系统遇到极值负荷的时候,可以有更强的容错能力,这种容错能力就是上面提到可以容忍系统调用性能的下降。

有关同步调用的问题链更详细的介绍可参考《让研发人员紧张的这条“故障神经线”(上)》

2、对状态考虑

这里的状态是我们一般说的,设计成有状态的还是设计成无状态的。最好是设计成无状态的。

啥叫状态,我们都知道HTTP通信是无状态的,请求-响应-结束,不会关心上下文,因为每次发送HTTP请求的时候不需要知道上一次发送的是什么内容。

那么,可能你会说,使用了cookie或者session,也保存了用户的会话信息。但这是借助了外力,HTTP本身就是无状态的通讯,这样非常简单。

根据AKF立方体的指导理论,我们沿X轴横向扩展。在这之前,我们只有一台WEB服务器,用户登录会话信息都可以保留在这一台服务器上面。

那么,横向扩展到几台WEB服务器共存的时候,你就需要考虑会话信息同步了,因为下一次的请求不一定会落在上一次请求的服务器上面。

当然解决的方法有很多,比如将会话保存在客户端,再者使用分布式缓存来保存,总之你需要多一份考虑。

如果我们沿Y轴扩展,做分库分表操作,那么问题也来了,对于所有用户的数据应该如何存放,一般我们是按照用户的USERID属性来做路由,这样用户的数据会分散到不同的分库或分表上面。

这样我们的应用程序在接收用户的数据请求的时候就需要多处理一层逻辑,需要根据USERID来匹配对于的分库分表,也需要多一份考虑。

因此,在实践了AKF之后,这些都是需要我们从设计上需要仔细考虑的。

扩展性的设计原则,当然不止上面两条,还有比如可监控的设计、多站点设计等等,本文结合我自己的亲身经历,特意选了通信方式和状态设计这两个来阐述。

四、故障

我们不能只专注于系统的扩展性而忽略了系统的故障风险,不然,到头来就是 “竹篮子打水一场空”,因为扩展性再好,系统漏洞百出,系统的使用者不能得到任何体验。

其中“复发的故障”便是扩展性的最大阻碍,每当生产环境中因同样的故障而造成的系统不可用,这种故障相当于盗窃了我们研发人员的时间和精力,因为它是一种重复的故障。

而我们追求的扩展性的原则就是用较少的成本来维护系统承接需求的能力,那么复发的故障就与这一原则相悖了。

我们如何来测量一个系统发生故障的可能性呢,在按照AKF实施了以后,比如Y轴扩展,把一个庞杂的系统按照功能去拆分,那么我们的一个系统所依赖的系统就会增多,这也是微服务的特点之一。

在微服务的环境下有好多个小而自治的系统存在。随着一个系统所依赖系统的增多,这个系统发生故障的几率也会增大。大致有如下这样的一个计算公式,我们以API GATEWAY系统为例。

从统计意义上讲,一个系统操作的可用性,由它所依赖的所有的服务共同决定。比如API GATEWAY 所依赖的服务1、服务2、服务3的可用性都是99.5%,那么API GATEWAY的可用性就是99.5% * 99.5% * 99.5% = 98.5%。

每一个额外的服务参与到其中,都会进一步降低API GATEWAY 的整体可用性。

五、总结

在软件领域一定是先有了动作,大家或者越来越多的人已经那样去做了,只是此时还没有人,没有那么一个牛人给抽象出来,一旦抽象出来之后,就有了概念。分布式、微服务、种种设计模式都是这样,AKF立方体也是这样。

我们什么时候进行X轴扩展,什么时候进行Y轴扩展,又在什么时候进行Z轴扩展呢。

一般情况下,交易量高、数据需求低、读多写少的系统,最经济的做法是采取X轴扩展。最经济的原因是这种方式,只是应用层的简单复制。

而对于那些用户数据增长较快,功能的复杂度增长也较快的系统,我们就需要考虑三个维度的扩展。

我的建议是在设计一个系统当初的时候三个维度就应该都需要有所考虑,这样当需求增长迅猛的时候我们可以快速扩展来满足用户的需求。

后记

说点题外话,也是大实话,我在京东的这些年,最恼人的是半夜凌晨收到报警打扰睡眠,周末休息时又被报警阻断了生活节奏。

有两种选择,选择一是离开它,选择二是战胜它。因此我无时无刻不在考虑如何保障平台生产的稳定性和扩展性。

所以我写的内容基本都是基于我工作的生产环境,有时候为了公司生产的保密性,然后在这个基础之上做了抽象总结。

希望每一篇文章对大家都能有所帮助。

往期文章

《写给关注我的你们》

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值