背景
架构设计不是架构师的专属工作,对非技术人员甚至是开发人员来说,从实实在在的需求到高神莫测的架构设计仿佛是一个神秘的过程,
只有具有架构师头衔的人才能掌握各中玄妙,这篇文章就是从最基本的事物关系来回答如何根据需求进行架构设计的问题。
根据我前面的文章,架构的本质是事物与事物之间恰当的关系,不同领域的架构,其事物的指代不同,
比如对于组织架构而言,事物指的是人与机构;建筑架构,事物指的是钢筋混凝土与空间。
那在软件领域,事物指的是什么呢?
我们知道,软件系统的本质是人类将自身无法处理的大量业务相关的数据进行筛选分类,并转换成计算机可以识别的格式,借助其强大计算能力来辅助处理。
因此在软件领域,架构中的事物指的是业务数据与基于运算能力的业务逻辑,说的再宽泛一点就是数据与处理数据的计算能力。
那么,架构设计其本质就是寻找数据、计算以及它们之间的平衡关系,这里面包括三个方面的要素,即 数据、计算、平衡关系 ,
其中数据和计算是架构设计的基础,根据实际业务需求一般不难找出,而平衡关系是综合考虑多方面得到的一种状态,也是衡量一个架构设计优劣的核心要素。
需求
1.数据
在对一个系统进行架构设计时,首先我们需要做的就是依据本系统所承载的业务需求,找出需要处理的最重要或最核心的数据,
这些数据一般隐藏在线下的纸质材料里,或者记录在日常办公的笔记里,或是约定俗成的共同认识,只要从实际业务出发,找这些数据并不难。
如果你无从下手,这里有个小窍门可以利用,
找一个出现率很高的业务,在该业务处理前尽可能多的记录一些可能与该业务相关的数据状态,待业务处理完成后,再次记录,并与之前的数据进行比较,
那些发生了变化的往往就是我们需要重点关注的重要数据。
举例来说:
如果这是一个政府行政办公的系统,那么办公流转过程就是数据,每个环节办理状态就是数据;
如果这是银行信用卡管理系统,那么用户信用卡可用金额、账单、有效期等状态信息就是数据,每笔刷卡流水就是数据;
如果这是电子商务系统,那么商品信息、用户订单、购物车信息就是数据。。。等等,
所有那些在实际业务过程中会变化的,并且是与该业务紧密相关的数据,都是我们需要找到的数据,
在所有已经找到的数据中,再依据实际业务的重要程度,找出最重要最核心的数据,作为在架构设计中我们需要重点处理的对象,
其他次重要的数据在核心数据充分处理的前提下作为平衡关系的备用因素。
2.计算
重要数据找到后我们还需要确定如何处理这些数据,即计算,说的明白一点就是计算逻辑是什么,计算逻辑类似但并不完全等同于业务逻辑,
它是业务逻辑在计算机世界里的一种体现,业务逻辑在真实世界里需要考虑人、时间、空间的因素,而计算逻辑在计算机的世界里,
是二进制码、CPU、内存、存储、网络等因素,
还是以上面的例子来说:
政府行政办公系统需要将线下的纸质签字盖章从发起请求到办结的全过程搬移到线上由系统处理,
那就需要转化成线上的在线申请、办理、流转、通知、办结、存档等过程,这些过程在线下可能有不同的部门来负责,
但是线上将由我们设计的系统完全支撑;
对于银行信用卡管理系统,需要将银行对信用卡的管理业务转化成具体的设置或查询可用金额、账单、有效期等信息的功能,
还有记录和统计用户消费流水等,如果业务有需求,甚至需要根据用户的消费流水对用户画像,以便进行精准营销等所谓的大数据分析模块;
电子商务系统也是一样,需要系统提供向用户展示商品信息,记录用户点击购买后的购物车信息,创建或更新用户的订单信息,
以及跟踪订单从仓库打包到送达的物流信息。。。等等,
这些都是我们对数据进行的动作,而动作不是我们凭空想象出来的,是从实际的业务处理转化到计算机领域而来的,
在转化的过程中我们需要时刻对应现实中的处理动作如何转换成计算机世界里的处理数据的能力。
由于寻找计算是一种业务动作的转化,在转化时我们可以多问自己期望系统应该如何帮我更好的处理数据,
那些利用机器能很好的完成而人工较难做到的但又是经常需要做的且与业务相关的动作一般都是我们需要找的,
常见的动作有:
数据跟踪记录、
查询统计、
修改更新、
导出展现、
汇总分析等。
当然有一点需要注意,我们在寻找计算因素的时候一定要基于计算机世界的客观现实,毕竟计算机不是万能的。
3.关系
明确了数据及如何处理数据,架构设计接下来要做的就是如何平衡好各种相互影响的关系,这些关系是所有我们能想到的会影响到系统的矛盾体,
数据处理效率与处理能力的关系、
数据体量与存储能力的关系、
数据展现与用户要求的关系、
系统部署与网络环境的关系、
系统建设与建设成本的关系、
系统易用性与客户要求的关系等等,
在做架构设计的时候要尽可能多的考虑到这些关系,并根据实际情况划分关系的重要程度,重点保障那些重要性高的关系, 毕竟再完美的架构设计也无法平衡好所有的关系,从这个角度来说,架构设计是一种平衡的艺术。 当然,要准确找出这些关系,并对它们划分重要性等级,还需要做到按等级进行平衡是需要经验积累的,非一朝一夕之功, 这也是人人都能做架构设计,但不是人人都能做好架构设计的原因。好在这一步并不是完全无规律可循的, 首先我们讲如何找出这些关系,虽然涉及影响一个系统的矛盾体很多,
但是大致上我们可以从以下3个方向来挖掘出这些关系:
这里的人包括筹建系统的甲方、建设系统的乙方、以及使用系统的用户, - 对于筹建系统的甲方来说,他一般关注系统的建设进度、成本、质量等, - 对于建设系统的乙方来说,重点会关注建设范围、风险、开发工具、实施环境等, - 对于用户来说,更关系系统易用性、界面友好,操作舒畅、能帮其解决实际问题等。
涉及到与人相关的关系,除了从经验中获取,更重要的是需要在前期系统设计的过程中通过调研的方式, 多与相关的干系人沟通,从他们那里获取,这也是为什么系统建设一般都是有需求调研过程的原因。 针对与人相关的关系这部分设计内容一般体现在架构设计说明书中的概述里,包括项目目标、项目背景及其他说明等, 当然与用户相关的一般也会在非功能性上有所体现,如易用性、可用性、安全等;
主要指其运行所在的操作系统及服务器,以及与之交互的外部系统,系统需要运行在服务器特定的操作系统上,受服务器操作系统计算存储网络等因素影响, 需要考虑服务器计算能力是否能处理数据、存储能力是否足够、网络是否稳定、如果服务器计算存储网络能力不够如何扩展等; 与外部系统的交互方面,本系统需要从外部系统获取哪些数据与能力、需要为外部系统提供哪些数据与能力、交互方式是什么、交互协议如何等。
一般来说,服务器的能力总是会有不够的,尤其是设计大数据量处理,大量用户同时访问的系统时, 这就需要我们根据系统的特点提前做好扩展的设计,高并发处理、分布式理论、多机房部署等这些技术概念可以给我们很好的指引, 这也是为什么架构师一定要眼界开阔的原因。
这部分的设计内容一般体现在架构设计说明书中的
逻辑架构、
技术架构、
接口设计、
部署架构、
性能、
可维护、
可扩展等非功能性设计上
数据是系统处理的主体,需要划分本系统所处理的数据与外部数据的边界,明确与外部数据的流向关系, 还需要根据实际业务来区分数据内部之间的关系,数据如何划分、各部分数据的边界在哪、与整体数据的关系如何等等。 在划分与外部数据的边界时要基于本系统所承载的实际业务内容,从业务出发,那些只受本业务影响的数据肯定在边界内, 而本业务与其他业务共同影响的还需要进一步分析哪方是影响主体,如果本业务是影响主体,那么在边界内,但是需要考虑提供给外部系统的交互接口, 如果本业务非影响主体,那么再看是否有间接影响或关联影响,一般来说这部分数据都要考虑与外部系统的交互关系。 对于边界内的数据关系也是如此,可以根据业务特点划分一些区块,每个区块内又是一个相对独立的单元, 与相关的其他区块单元存在哪些数据上的直接或间接影响,他们之间如何交互等。所有这些关系都是我们需要发现并在架构设计时考虑的。 针对这部分的设计内容一般体现在架构设计说明书中的数据架构、整体架构里。
人、外部系统、数据是我们在发掘关系时可以参考的方向,根据系统各自的特点,在架构设计过程中还会有一些需要实际去考虑的关系,
这些关系一般都是所谓的系统最大的特点或特殊情况,常见于重大需求,特色需求,亮点需求等形式,一般也不难找出。
待把所有这些关系找出后,可以先做一个粗略的重要性分级,分级的依据是关系的相关性,
重要需求相关>特色亮点需求>甲方相关>用户相关>乙方相关>外部系统相关>外部数据相关>内部数据相关>其他次重要的数据,
在进行架构设计时优先满足重要性高的关系,得出一个基本的架构雏形,再根据弱一级的关系不断地优化完善架构模型,
待大部分关系都可以满足后,架构设计也就出来了。
当然,很多关系之间都是矛盾的,
比如:
筹建系统的甲方要求的低成本与高质量、
系统间数据交互与操作舒畅等,
需要我们在做架构设计时不断权衡,尽可能的兼顾,对于实在无法兼顾的,需要进行权衡取舍。
综上来说,架构设计就是一个 找准数据主体、明确处理逻辑、平衡矛盾关系的过程 ,
需要根据实际业务进行适当的抽象,使之适合体现在计算机的世界,每一步都需要我们明确主体,分清主次,并尽可能的平衡更多的关系,
这需要不断的积累经验,也靠一点悟性,有时候也需要一些灵感。
无论如何,架构设计都不只是架构师的工作,而是任何人都可以做的一项有趣的工作,
愿你看完此篇文章后对架构设计不再迷茫,逐步成为一个优秀的架构师。
技术评审提纲
业务项目千差万别,没有一个统一的方法论完成架构设计和技术评审,架构设计只需要从某些关键点来表达系统即可, 提纲就是用来帮助大家做架构评审的工具,帮助大家整理思路并形成可实施的方案, 因此在做系统设计时,可有选择性的参考此提纲,根据业务特点来完成一个可实现的有效的架构设计。
业务背景
项目名称
业务描述
技术背景
架构描述
当前系统容量(系统调用量平均值)
当前系统调用量峰值
业务需求
要改造的需求
要实现的需求
性能需求
预估系统容量(预估系统调用量平均值)
预估系统调用量峰值
其他非功能质量
概述
一句话概括方案的亮点,比如说: 双写,主从分离,分库分表,扩容,归档等。
详细说明
方案的具体描述,文字描述不清楚的话可以结合图(任何图:UML,概念图,框图等)的方式说明, 如果是改造方案最好突出变动的地方,以下列举了几种描述的角度: * 中间件架构(应用服务器、数据库、缓存、消息队列等) * 逻辑架构(模块划分、模块通信、信息流、时序等) * 数据架构(数据结构、数据分布、拆分策略、缓存策略、读写分离策略、查询策略、数据一致性策略) * 异常处理,容灾策略,灰度发布
性能评估
给出方案的基准数据,并按性能需求评估需要使用的资源数量。 单机并发量 单机容量 按照预估性能需求,预估资源数量(应用服务器、缓存、存储、队列等) 伸缩方式
方案优缺点
列出方案的优缺点,优缺点要具有确定性,不要有“存在一定风险”这种描述,也就是要量化。
等等
对比可选方案,并给出选择这种方案的理由,选择倾向的方案,
标识所选方案的风险,提出解决此风险发生时候的应对策略,比如:上线失败时的回滚策略。
描述使用所选方案需要做的具体工作,并评估开发、测试等细化任务需要的时间,形成可实施的任务计划表,
任务计划表推荐采用简单的表格形式,减少工具使用和学习的成本。
物流系统包含如下两个质量优先需求:
维护会员常用地址,下单时提供会员地址列表。
下单时异步产生物流订单,物流系统后台任务从第三方物流轮循拉取物流状态,已经下单用户查询订单的物流订单和物流记录。
由于会员数量较大,可能有较快的增长速度,订单数量更是巨大,促销期峰值的订单产生量可能很高,这两个业务模块的数据存储需要分库分表,
并借助消息队列和缓存抗写和读的流量,因此,本方案主要涉及这两个业务的容量评估。
选取行业内一线电商平台的量级作为目标:
会员量2亿,平均增长5万/天。
平时订单量400万/天,所有订单下单时段集中在9:00-23:00,促销日订单量1400万/天,50%订单下单时段集中在晚上7:30-8:30和晚上22:00-23:00。
通用标准
容量按照峰值5倍冗余计算。
会员常用地址容量按照30年计算,而物流订单时效性较强按照3年计算。
第三方查询接口5000 QPS。
Mysql
单端口读:1000 QPS
单端口写:700 TPS
单表容量:5000万条
Redis
单端口读:4万 QPS
单端口写:4万 TPS
单端口内存容量:32G
Kafka
单机读:3万 QPS
单机写:5000 TPS
应用服务器
请求量每秒峰值:5000 QPS
由于整个电商网站刚刚上线,数据量级还无法清晰的确定,我们根据行业内知名电商当前数据量级设计最大性能方案,
本方案可以应对行业内电商巨头的各种促销所带来的服务请求峰值,并且拥有最快的响应时间,达到服务性能的最大化。
需求1. 会员常用地址
提供Restful服务增加会员常用地址。
提供Restful服务获取会员常用地址列表。
数据库资源评估:
读QPS:
会员每次下单,拉取一次会员地址列表,按照促销日订单量1400万/天,50%订单下单时段集中在两个小时内计算:
(1400万 × 0.5) / (2 × 60 × 60) = 1000/秒
容量评估按照5倍冗余计算,读QPS峰值1000/秒 * 5 = 5000/秒,需要5端口数据库服务读。
写TPS:
假设每天增加的会员全部添加一次常用地址,并且高峰期会员下订单时有20%的会员会增加一条常用地址:
(1400万 × 0.2 + 5万) / (2 × 60 × 60) = 400/秒
容量评估按照5倍冗余计算,400/秒 * 5 = 2000/秒,需要3端口数据库服务写。
当前有2亿会员,每天增长5万会员,平均每个会员有5个常用地址,30年会员常用地址表数量计算:
(2亿 + 5万 × 365 × 30年) × 5 = 35亿
容量评估按照5倍冗余计算,35亿 * 5 = 175亿,需要350张表即可容纳。
根据以上读QPS、写TPS的评估,如果读写混布我们共需要8端口,可以使用8主8备,
如果读写分离,我们需要做主从部署,需要3主6从,与2倍数对齐,使用4主8从即可。
根据表容量,需要350张表,和2的指数对齐,选择512张表,上面计算需要主库端口为4,
考虑到将来端口扩展不用拆分数据库,尽量设计更多的库,使用32个库。
设计结果:4端口 × 32库 × 4表, 4主8从
为了提高用户下单的体验,需要使用Redis缓存活跃用户的常用地址。
定义当天下订单的会员为活跃会员,活跃会员的地址缓存24小时,
假定每天下订单的会员均为不同会员,每个会员有5个常用地址,缓存大小计算如下:
1400万 × 5 × 1k = 70G
容量评估按照5倍冗余计算,70G×5=350G,按照每台Redis 32G内存计算,需要11台机器,
根据数据库对数据存取QPS/TPS的设计,11台机器完全可以满足5000/秒的读QPS和2000/秒的写TPS。
设计结果:11台,主从
根据数据库的读QPS(5000/s)峰值和写TPS(2000/s)峰值计算,单台应用服务器即可,选择2台避免单点。
设计结果:2台
需求2: 物流订单和物流记录
订单提交后,通过消息队列产生物流订单,消息传入物流系统,物流系统消费物流订单消息然后入库。
后台任务轮循未完成物流订单,查询第三方物流接口状态,填写物流记录信息。按照每天1400万的订单,订单平均3天到货,第三方查询接口5000 QPS,
每次状态查询需要时间计算如下:1400万 × 3 / 5000 = 8400 / 60 / 60 = 2小时,定时任务2小时查一次
提供REST服务获取物流订单信息。
提供REST服务获取物流记录信息。
提供REST服务获取物流订单和物流记录信息。
数据库资源评估
读QPS:
会员下单三天到货,三天内50%客户会查询一次物流订单和一次物流记录,计算如下:
(1400万 × 3 × 0.5) / (24 × 60 × 60) = 250/秒
容量评估按照5倍冗余计算,2 × 250/秒 × 5倍 = 2500/秒,需要3端口数据库服务读。
写TPS
会员每次下单,产生一次物流订单,按照促销日订单量1400万/天,50%订单下单时段集中在两个小时内计算:
(1400万 × 0.5) / (2 × 60 × 60) = 1000/秒
按照每天1400万的订单,订单平均3天到货,每条物流订单产生8条物流记录,并且8条物流记录在三天内均匀产生,物流记录写TPS计算如下:
1400万 × 3 × 8 / 3 / (24 × 60 × 60) = 1200/秒
当前2亿物流订单积累,每天增长400万订单,30年订单数量计算:
2亿 + 400万 × 365天 × 3年 = 46亿
容量评估按照5倍冗余计算,46亿 * 5 = 230亿,需要460张表即可容纳, 物流记录表是物流订单的8倍,460 × 8 = 3680张表。
根据以上读QPS和写TPS,如果读写混布,我们共需要18端口,18主18备,如果读写分离,我们需要16主16从。
根据表容量,需要3680张表,和2的指数对齐,选择4096张表,上面计算需要主库端口为16,考虑到将来端口扩展不用拆分数据库,尽量设计更多的库,使用32个库。
设计结果:16端口 × 32库 × 8表,16主16从
为了让系统能够应对峰值的突增,采用消息队列Kafka接收物流订单。
根据上面对写TPS的计算,考虑5倍冗余后,峰值为5000/秒,单台Kafka和单台处理机即可处理。
如果峰值有突增,可以增加Kafaka集群的节点来抗写流量,处理机根据后端入库性能来决定。
例如写峰值增加10倍,达到5万/秒,需要10台Kafka,每台Kafka读QPS可达3万,理论上需要2台处理机,然而,处理机的瓶颈是后端入库的写TPS,
根据上面计算,入库的写TPS峰值按照5000/秒设计,因此,单台处理机即可,这个场景下会有消息的堆积,但是最终会处理完毕,达到消峰的效果。
设计结果:1台Kafka,主从,1台处理机
根据数据库的读QPS(2500/s)峰值和写TPS(11000/s)峰值计算,3台应用服务器即可。
用于查询第三方接口的后台任务服务器,由于受到第三方接口5000/s的QPS的限制,单台机器即可,为了避免单点,2台处理机即可。
设计结果:2台
由于当前系统线上数据量并不多,增长量也不大,读QPS和写TPS单台机器完全可以处理,暂时不考虑使用缓存和消息队列,
但是保留使用缓存和消息队列的接口,如果缓存和消息队列的资源可用,可以通过开关进行切换。
当前的数据量使用单库单表即可处理,然而,考虑到将来扩容方便,数据库端口暂时使用一个,但是保留我们在最大性能方案中对数据库的分库分表,
当读QPS和写TPS突增时,DBA可以把库重新拆分到多个端口来抗请求流量。
因此,方案如下:
需求:会员常用地址
设计结果:1端口 × 32库 × 16表, 1主1从
需求:物流订单和物流记录
设计结果:1端口 × 128库 × 32表,1主1从
当前线上流量并不大,使用最小资源方案节省成本。
最小资源方案充分的考虑了数据库的分库分表,当读QPS和写TPS突增时,DBA可以拆分库到不同的端口,也就是增加端口来应对。
最小资源方案在应用层设计了开关,如果性能突增可以临时申请和开启缓存和消息队列。
本文以互联网企业重点关注的非功能质量为主线,总结了非功能质量需求的总体目标,并针对不同的服务和资源列举了不同的非功能质量需求,
帮助读者在做技术评审的过程整理思路,尽量穷举评审时关注的评审点,并随后提供了一个简单有效的评审提纲,
最后根据提纲实现一个互联网容量和性能评估的经典案例,大家可以在案例中了解高并发互联网系统是如何进行拆分的,以及依据哪些数据进行拆分。
由于本文的数据完全是基于笔者在某个互联网平台下的经验而记录的,并不代表可以直接应用在任何企业和平台上,
这里重点突出进行容量和性能评估的方法论,帮助大家整理实现高并发互联网系统的思路。
历
QPS、TPS、并发用户数、吞吐量关系
史
谷歌开源内部代码评审规范
文
UML (统一建模语言) 各种图总结
章
真实项目案例实战—【状态设计模式】使用场景
欢迎分享转发,有帮助的话点个“在看”