架构设计: 如何提供设计方案

面试时你是否常被问到这样的问题:“你之前是如何设计这个系统(或子系统/模块/功能)的?请介绍你的思路。”

很多研发同学在听到类似的面试题时,往往忽略“系统设计思路”关键词,而是陷入某个技术点细节里,让面试官听得一头雾水。这样即使技术再好,面试官也很难给你打高分,更可能认为你的设计能力不足,没有全局思维。

而要想答得更好,你要用架构师的视角回答,即从全局技术视角阐述设计的过程。接下来我会通过一个案例,讲解如何从全局技术视角介绍自己的技术方案。

案例背景

在电商中,当用户发表一条商品评论,后台的逻辑是点评系统会调用一系列的远程 API 接口,如调用风控系统、广告系统、消息系统……几个甚至十几个系统的接口

在业务建设之初,考虑到快速开发与上线,商品评论发布是通过同步 RPC(Remote Procedure Call,远程过程调用)远程调用各系统接口完成的。这种方式在系统少、逻辑简单的阶段很符合实际情况的设计。

但随着业务快速发展,通过 RPC 同步调用的问题逐渐暴露出来。由于过多地依赖其他系统,导致评论发布的接口性能很低,可用性也容易受到其他系统影响。而且每当点评系统需求上线时,其他系统都需要跟着进行联调测试,导致需求迭代速度缓慢

在这里插入图片描述
在做系统架构升级改造时,如果你有互联网设计理念,会很容易想到问题在于系统间的耦合度太高。解决办法就是采用异步化解耦,从而通过引入 MQ 消息管道,在架构上进行系统业务逻辑拆分,将原本强依赖的系统间的同步 RPC 调用变成异步消息触发,如下面图片中的架构所示:

在这里插入图片描述

案例分析

对于上面的案例,假设你是应聘者,当被问“如何做这个点评系统的改造?”时,你会怎么回答?你会不会直截了当地说“我引入了 MQ 消息队列,做了系统解耦,采用异步消息通知的方式来触发系统调用”呢?

在互联网系统设计方案如此透明的今天,随便在网上搜一下都会有大量类似的解决方案。以上回答不但不会让面试官满意,甚至有可能令人怀疑你的项目经历的真实性。

作为研发工程师,正确的回答方式是要让面试官知道你解决问题的思维。相比一上来就说用了什么技术,阐述解决思维更能证明你的能力,因为解决技术问题的方法有很多,这是“术”,但解决技术问题的底层思维逻辑是一样的,这是“道”。

面对此类问题,我总结了如下四个层面的答案:

1、谈复杂来源;
2、谈解决方案;
3、谈评估标准;
4、说技术实现。

问题解答

复杂来源

之所以要先分析系统的复杂度,是因为只有正确分析后才能明确设计原则,进而设计架构方案,整体项目才不会找错方向。

如果一个系统本来因业务逻辑复杂导致功能耦合严重,你却设计了一个 TPS(Transactions Per Second,每秒事务处理量)达到 10000/秒 的高性能架构,那么即使架构性能再优秀,也没有现实意义,因为技术设计没有解决主要问题的复杂度。这是很多研发工程师的通病,设计偏离了方向,只是为了设计而设计。

那么如何正确评估系统的复杂度呢? 互联网软件通常分为功能性的复杂度和非功能性的复杂度两种。我将分析过程制作成了一张图片。

在这里插入图片描述
从功能性复杂度方面来看,你可以从案例中得知,产品业务发展快速、系统越来越多、协作效率越来越低。作为系统负责人,你敏锐地发现问题根源在架构上各业务子系统强耦合。于是你引入消息队列解耦各系统,这是系统业务领域带来的本质上的复杂度,也就是功能性的复杂度,解决的是系统效率的问题。

此外,对于互联网系统设计,还需要考虑非功能性的复杂度,例如高性能、高可用和扩展性等的复杂度的设计。

从非功能性复杂度方面来看,我们假设系统用户每天发送 100 万条点评,那么点评的消息管道一天会产生 100 万条消息,再假设平均一条消息有 10 个子系统读取,那么每秒的处理数据,即点评消息队列系统的 TPS 和 QPS(Queries Per Second,每秒查询次数)就分别是 11(1000000/606024)和 115(10000000/606024)。

不过系统的读写不是完全平均的,设计的目标应该以峰值来计算,即取平均值的 4 倍。于是点评消息队列系统的 TPS 变成了 44,QPS 变成了 460,这个量级的数据意味着并不需要设计高性能架构方案。

接着还要考虑业务规模发展。架构设计的目标应该满足未来业务增长,我们把未来业务增长的预估峰值设定为目前峰值的 4 倍,这样最终的性能要求分别是:TPS 为 176,QPS 是 1840。这样的读写指标还达不到系统压测的性能基线,所以可以确定的是点评系统的复杂度并不在高性能问题上。

对于点评系统来说,还需要考虑高可用的问题。假设点评系统的消息队列挂掉,将导致用户评论发送失败,当然在用户体验层面,解决方式可以在页面端提示用户重新操作,但如果问题影响到了点评消息的读取,导致评论没有走风控策略,就会造成严重的影响。所以高可用性是点评系统的设计复杂度之一,包括点评写入、点评存储,以及点评消息的读取,都需要保证高可用性。

为了方便理解非功能性的复杂度,我只分析了“高性能”和“高可用”这两点,在实际应用中,不同的公司或者团队可能还有其他方面的复杂度分析。例如有的公司会考虑安全性,有的公司会考虑成本等。

所以综合分析来看,点评系统改造的复杂度来源于两点。

  • 功能性复杂度:要解决业务发展带来的系统耦合、开发效率缓慢问题。
  • 非功能性复杂度:要保证系统的高可用性。

解决方案

在确定了系统面临的主要复杂度问题后,就有了明确的方案设计目标,这时就可以开始进行架构方案设计了。我同样会结合本文的案例场景,谈谈点评系统消息管道的架构设计解决方案

1、采用开源的 MQ 消息管道。目前 MQ 消息管道有很多开源解决方案,比如 Kafka、RocketMQ、RabbitMQ 等。在实际项目中,你可以根据不同的应用场景选择合适的成熟开源消息队列方案,这是很多公司常用的做法。

2、采用开源的 Redis 实现消息队列。方案 1 虽然应用了开源 MQ 实现点评消息的通信,但是因为引入一个消息中间件就会带来运维成本,所以方案 2 可以基于轻量级的 Redis 实现,以降低系统的维护成本和实现复杂度。

3、采用内存队列 + MySQL 来实现。方案 2 中虽然应用了较为轻量级的 Redis 来实现,但是还需要引入一个缓存系统,同样也会带来运维成本,所以方案 3 是直接基于 MySQL 实现,即基于内存队列的方式,异步持久化到数据库,然后通过定时任务读取 MySQL 中的消息并处理。

一般情况,你至少要设计两到三套备选方案,考虑通过不同的技术方式来解决问题。方案设计不用过于详细,而是要确定技术的可行性和优缺点。

评估标准

设计完三套解决方案之后,摆在眼前的问题就是需要选择最合适的一个。这就需要一套评估标准了。

在互联网软件架构中,架构师常常会把一些通用的设计原则写到设计文档中,比如设计松耦合、系统可监控,这些原则似乎不常用,但好的架构师会通过设计原则来控制项目的技术风险。比如系统无单点,限制了系统技术方案不可出现单点服务的设计;再如系统可降级,限制了系统有具备降级的能力,进而约束了开发人员需要设计数据兜底的技术方案。

这些看似不重要的设计原则,其实是评估架构解决方案的重要手段。做系统架构,需要站在更高的层面考虑系统的全局性关注点,比如性能、可用性、IT 成本、投入资源、实现复杂度、安全性、后续扩展性等。这在不同场景的不同阶段会起到决定性作用。

那么针对案例中的点评系统来说,要如何评估方案呢?这要从点评系统的复杂度来源进行评估。

点评系统功能性复杂度

点评系统的功能性复杂度问题,本质上是随着业务发展带来的系统开发效率问题。解决这个问题要试着站得更高一些,以部门负责人的视角,考虑现有研发团队的能力素质、IT 成本、资源投入周期等因素是否匹配上面三种架构解决方案。

点评系统非功能性复杂度

为了解决系统的高可用,可以参考三个设计原则。

第一个是系统无单点原则。首先要保证系统各节点在部署的时候至少是冗余的,没有单点。很显然三种设计方案都支持无单点部署方式,都可以做到高可用。

第二个是可水平扩展原则。对于水平扩展,MQ 和 Redis 都具有先天的优势,但内存队列 + MySQL 的方式则需要做分库分表的开发改造,并且还要根据业务提前考虑未来的容量预估。

第三个是可降级原则。降级处理是当系统出现故障的时候,为了系统的可用性,选择有损的或者兜底的方式提供服务。

常用手段主要有三种。

  • 限流,即抛弃超出预估流量外的用户。
  • 降级,即抛弃部分不重要的功能,让系统提供有损服务,如商品详情页不展示宝贝收藏的数量,以确保核心功能不受影响。
  • 熔断,即抛弃对故障系统的调用。一般情况下熔断会伴随着降级处理,比如展示兜底数据。

针对案例场景中三个解决方案的降级策略,在一般的情况下,我们默认数据库是不可降级的,MQ 和 Redis 都可以通过降级到数据库的方式做容灾处理。所以案例中的三个解决方案,MQ 和 Redis 要考虑降级到 MySQL 或其他方式,这里就还需要根据情况投入降级的开发成本。

对于本节课的案例我不评价哪个更好,你在多个解决方案中做选择时,不要陷入某个纯粹技术点的优劣之争,那样很难有结果,越大的项目越明显。 通常来说,方案没有优劣之分,而是要看哪个更适合当下的问题,只要架构满足一定时期内的业务发展就可以。

你要知道,作为技术人,考虑问题的方式要比具体的选型结果更为重要,这是面试的加分点。

技术实现

在确定了具体的架构解决方案之后,需要进一步说明技术上的落地实现方式和深层原理,如果你最终选择基于 Redis 来实现消息队列,那么可以有几种实现方式?各自的优缺点有哪些?对于这些问题,要做到心里有数。比如,基于 Redis List 的 LPUSH 和 RPOP 的实现方式、基于 Redis 的订阅或发布模式,或者基于 Redis 的有序集合(Sorted Set)的实现方式,你可以自行搜索,我不再赘述。

总结

最后,我把今天的“四步回答法”做个总结,加深每一步你需要掌握的注意点。

1、在回答系统复杂度来源的时候,要注意结合具体的业务场景和业务发展阶段来阐述。业务场景表明了业务的独特性,发展阶段表明了业务的成熟度,因为同一业务场景在不同阶段产生的矛盾也是不同的。

2、在回答解决方案的时候,有价值的解决方案一定是建立在明确复杂度来源基础之上的。所以在设计架构的时候才分主要问题和次要问题,主要问题是必须要解决的点,次要问题可以根据实际情况进行取舍。

3、在回答如何评估架构方案时,至少要从功能性和非功能性两个角度出发判断方案的合理性。对于很难决策的方案,要从更高的视角(比如技术负责人、业务负责人的角度)进行考量。

4、在技术实现的细节上,要尽量讲出技术的实现原理,不要浮于表面的框架组合。

所谓的架构师视角就是全局的视角,这里的全局包括空间全局和时间全局,在空间全局上你要看到整个系统的领域边界,在时间全局上你要看到整个系统的发展周期。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/630615.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

各省快递量数据, shp+excel,2001-2021年,已实现数据可视化

基本信息. 数据名称: 各省快递量数据 数据格式: shpexcel 数据时间:2001-2021年 数据几何类型: 面 数据坐标系: WGS84 数据来源:网络公开数据 数据字段: 序号字段名称字段说明1a_2001快递量/万件_2001年2a_2002快递量/万件_2002年3…

ceph数据分布式存储

单机存储的问题 存储处理能力不足 传统的IDE的IO值是100次/秒,SATA固态磁盘500次/秒,固态硬盘达到2000-4000次/秒。即使磁盘的IO能力再大数十倍,也不够抗住网站访问高峰期数十万、数百万甚至上亿用户的同时访问,这同时还要受到主机…

软件测试|使用Python轻松裁剪视频

简介 裁剪视频是在视频编辑和处理中常见的任务之一,Python提供了多种库和工具,可以用来裁剪视频。在本文中,我们将详细讨论如何使用Python来裁剪视频,并提供示例代码。 步骤1:环境准备 首先,我们要安装必…

Firefox 100 正式发布

五月三日,Firefox发布了它的第100个版本,来回顾一下Firefox是如何走到今天这一步的,以及在第100个版本中发布了哪些功能。 回顾 2004年,《纽约时报》上宣布了Firefox 1.0的发布,这个广告列出了为第一版做出贡献的每一…

C语言——小细节和小知识12

一、倒置句子 将句子中的单词位置倒置,标点不用倒置,例如i love you.倒置结果是:you. love i。 1、两步翻转法 采用两步翻转法来实现单词位置的倒置。首先,它整体翻转整个字符串,然后再逐个翻转每个单词内的字符。 …

redis安装-Linux为例

可以下载一个Shell或者MobaXterm工具,便于操作 在redis官网下载压缩包 开始安装 安装依赖 yum install -y gcc tcl切换目录 切换目录后直接把redis安装包拖到/user/local/src/下 cd /user/local/src/解压然后安装 #解压 tar -zxvf redis-7.2.4.tar.gz #安装 …

day13

1.多态的向上转型和向下转型向上转型: 父类的引用指向子类的对象Person person new Man();向下转型: 将父类的引用强转为子类的对象Man man (Man) person; 2.instanceof关键字的用法引用 intanceof 运行类型 3.抽象类声明方式abstract class Person {} 4.接…

python数字图像处理基础(六)——模板匹配、直方图

目录 模板匹配概念单对象模板匹配多对象模板匹配 直方图1.查找直方图2.绘制直方图3.掩膜的应用 模板匹配 概念 模板匹配和卷积原理很像,模板在原图像上从原点开始滑动,计算模板与图像被模板覆盖的地方的差别程度,这个差别程度的计算方法在o…

如何安装“Nextcloud 客户端”win10系统?

1、 下载 Nextcloud的官网 Download and install Nextcloud 2、安装 3、 Nextcloud登录

组件v-model(.sync)记录使用(vue3)

示例(演示地址) 以下是Vue3中使用v-model实现组件的双向数据绑定的示例代码: 首先,让我们来了解一下Vue3中v-model的用法。在Vue3中,v-model 指令可以用于自定义组件上,用于实现组件的双向数据绑定。与Vue2…

Alinx ZYNQ 7020 LED调试--in RAM

设置拨码开关为JTAG方式 烧写LED bit stream a. 点击“Program device”烧录程序到FPGA中(重新上电程序就丢失了) b. /01_led/led.runs/impl_1/led.bit 程序烧录到Flash中 ZYNQ与以往的直接烧录Flash不同,首先必须PS,然后烧…

spring-boot定时任务

org.springframework.boot jar包 内置定时任务注解 。生成定时任务有 * * * * * ? 表示秒分时日月周。 日和周的位置 必须某个位置用?代替*号用于区别。 定时任务规则:0 * * * ? * * 表示任意月的任意周的每天的每时的每分…

抖音矩阵云混剪系统源码(免授权版)多平台多账号一站式管理,附带系统搭建教程

搭建教程 MySQL 5.6 PHP 7.2 Apache 数据库名称 juzhen Nginx环境切换伪静态 1、解压安装包到项目根目录,找到application/database.php 更换自己的数据库密码 2、阿里云现有的配置不要动 其他按照文档进行添加 3、项目访问目录:public 4、域名…

Demo: 实现PDF加水印以及自定义水印样式

实现PDF加水印以及自定义水印样式 <template><div><button click"previewHandle">预览</button><button click"downFileHandle">下载</button><el-input v-model"watermarkText" /><el-input v-mo…

敏捷开发之Scrum

敏捷开发是什么 我们一般习惯用瀑布模型&#xff0c;它以文档为驱动&#xff0c;将软件生命周期划分为固定的六个基本活动&#xff0c;并且规定了它们自上而下、相互衔接的次序&#xff0c;如同瀑布流水&#xff0c;逐级下落。 那什么是敏捷开发呢&#xff1f; ​ 敏捷开发的核…

代码随想录算法训练营第五天| 总结数组专题

数组&#xff1a;二分查找、双指针&#xff08;包括快慢指针&#xff09;、滑动窗口、模拟 链表&#xff1a;双指针、三指针、虚拟头指针、复杂指针操作画图明确每一步&#xff08;标好次序&#xff09; 数组 代码随想录总结的很好&#xff0c;如下图。我再结合自己的一些理解…

AI 的未来是开源的

想象一下&#xff0c;在未来&#xff0c;人工智能不会被锁在公司的金库里&#xff0c;而是由全球创新者社区一砖一瓦地在开放中构建的。协作&#xff0c;而不是竞争&#xff0c;推动进步&#xff0c;道德考虑与原始绩效同等重要。这不是科幻小说&#xff0c;而是人工智能发展核…

C++I/O流——(4)格式化输入/输出(第二节)

归纳编程学习的感悟&#xff0c; 记录奋斗路上的点滴&#xff0c; 希望能帮到一样刻苦的你&#xff01; 如有不足欢迎指正&#xff01; 共同学习交流&#xff01; &#x1f30e;欢迎各位→点赞 &#x1f44d; 收藏⭐ 留言​&#x1f4dd; 含泪播种的人一定能含笑收获&#xff…

73.网游逆向分析与插件开发-背包的获取-物品数据的初步数据分析

内容参考于&#xff1a;易道云信息技术研究院VIP课 上一个内容&#xff1a;72.网游逆向分析与插件开发-背包的获取-项目需求与需求拆解-CSDN博客 然后首先找切入点&#xff1a; 通过药物来当切入点&#xff0c;药物比较好使用&#xff0c;然后鼠标放到药物上它有名字、种类、…

【分布式技术】分布式存储ceph之RGW接口

目录 1、对象存储概念 2、创建 RGW 接口 //在管理节点创建一个 RGW 守护进程 #创建成功后默认情况下会自动创建一系列用于 RGW 的存储池 #默认情况下 RGW 监听 7480 号端口 //开启 httphttps &#xff0c;更改监听端口 #更改监听端口 ​ //创建 RadosGW 账户 …