架构实践01-基础概念

零、文章目录

架构实践01-基础概念

1、架构是什么

(1)定义
  • 架构:软件系统的顶层结构,描述了系统的整体设计和组成部分之间的关系。
  • 框架:组件规范,提供基础功能的产品,帮助开发者实现功能。
  • 组件:自包含、可编程、可重用的软件单元。
  • 模块:逻辑上划分的系统单元,负责特定的职责。
  • 系统:由关联个体组成的整体,具有新的能力。
  • 子系统:更大系统中的一部分,同样由关联个体组成。
(2)区别与联系
  • 系统与子系统:
    • 系统:由多个有关联的个体组成,按照特定规则运作,产生新的能力。
    • 子系统:观察角度不同,可以是更大系统的一部分。
  • 模块与组件:
    • 模块:逻辑角度拆分系统,职责分离。
    • 组件:物理角度拆分系统,单元复用。
  • 框架与架构:
    • 框架:关注规范,提供基础功能。
    • 架构:关注结构,描述系统设计。
(3)实际应用
  • 微信架构:
    • 微信:系统,包含聊天、登录、支付、朋友圈等子系统。
    • 朋友圈:子系统,包含动态、评论、点赞等子系统。
    • 评论:子系统,包含防刷、审核、发布、存储等模块或组件。
  • 学生信息系统:
    • 逻辑角度:登录注册模块、个人信息模块、个人成绩模块。
    • 物理角度:Nginx、Web 服务器、MySQL、ElasticSearch。
(4)架构的多角度理解
  • 业务逻辑角度:描述业务模块的组成和职责。
  • 物理部署角度:描述系统各部分的物理分布和交互方式。
  • 开发规范角度:采用特定的框架(如MVC)来实现系统功能。
(5)架构的重要性
  • 顶层设计:明确系统包含哪些个体,个体如何运作和协作。
  • 多维度:从不同角度分解系统,形成不同的架构视图。
  • 灵活性:适应不同场景和需求,确保系统的可扩展性和可维护性。

2、架构设计的历史背景

(1)软件开发的历史背景
  • 机器语言(1940年之前):
    • 直接使用二进制码表示指令和数据,极其难写、难读、难改。
  • 汇编语言(20世纪40年代):
    • 使用助记符和地址符号,解决了机器语言的复杂性,但仍需了解底层细节。
  • 高级语言(20世纪50年代):
    • 让程序员无需关注机器底层,只需关注具体问题,提高了开发效率和可移植性。
  • 第一次软件危机(20世纪60年代~70年代):
    • 软件规模和复杂度增加,导致项目延期、超支、质量低下等问题。
    • 提出"软件工程"和"结构化程序设计"来应对。
  • 第二次软件危机(20世纪80年代):
    • 随着硬件发展和业务需求复杂化,软件扩展性问题突出。
    • 面向对象编程开始流行,成为主流开发思想。
(2)软件架构的历史背景
  • 模块化(20世纪60年代):
    • 解决软件逻辑复杂性。
  • 面向对象(20世纪80年代):
    • 解决软件扩展性问题。
  • 组件化(20世纪90年代):
    • 适应更大规模的软件系统,进一步降低复杂度。
  • 20世纪90年代:
    • 软件架构概念开始流行,主要在大公司中应用。
    • 面临的问题包括系统规模庞大、内部耦合严重、开发效率低、扩展困难等。
    • 软件架构的目的是通过组件化设计,降低系统复杂度,提高可维护性和扩展性。
(3)为什么没有银弹
  • 复杂性和变更:
    • 软件开发面临的核心挑战是复杂性和变更。
  • 有限资源:
    • 在有限的资源下,需要找到平衡点,没有一种方法论能解决所有问题。
  • 历史背景和环境变化:
    • "银弹"产生于特定的历史背景和大环境,随着环境的变化,原有的解决方案可能不再适用。
  • 问题空间的扩展:
    • 问题空间的扩展速度远超解空间,需要不断提出新的解决方案。

3、架构设计的目的

(1)架构设计的常见误区
  • 架构的重要性:很多人认为架构很重要,但并没有明确为何重要。
  • 架构设计的必要性:有些人认为不做架构设计系统就无法运行,但实际上,简单的系统可以没有正式的架构设计。
  • 提升开发效率:架构设计不一定能提升开发效率,有时简单的设计反而更高效。
  • 促进业务发展:良好的架构设计有助于业务发展,但复制成功企业的架构并不能保证同样的成功。
  • 形式主义:有些公司因为流程规定或架构师需要做事而进行架构设计,这往往是不必要的。
(2)架构设计的真正目的
  • 应对软件系统复杂度:架构设计的主要目的是为了解决软件系统复杂度带来的问题。
  • 识别复杂度:通过熟悉和理解需求,识别系统复杂性所在的地方,然后针对性地进行设计。
  • 避免贪大求全:不要盲目追求高性能、高可用、高扩展等特性,而是要根据实际需求进行设计。
(3)实践中的复杂度分析
  • 性能:评估系统的性能需求,确定是否需要高性能设计。
  • 可扩展性:分析系统的扩展需求,确定是否需要高扩展性设计。
  • 高可用:评估系统的可用性需求,确定是否需要高可用设计。
  • 安全性:分析系统的安全需求,确定必要的安全措施。
  • 成本:考虑系统的成本,确保设计在预算范围内。
(4)架构设计的指导思想
  • 解决实际问题:架构设计应聚焦于解决实际的复杂度问题,而不是盲目追求技术先进性。
  • 权衡取舍:在性能、可靠性、扩展性、安全性和成本之间做出合理的权衡。
  • 适应业务需求:架构设计应紧密贴合业务需求,避免过度设计。
(5)架构设计三原则
  • 合适原则
    • 合适优于业界领先:选择适合当前业务需求和团队能力的技术方案,而不是一味追求最先进的技术。
    • 将军难打无兵之仗:资源有限时,应选择团队熟悉且能够快速落地的技术方案。
    • 罗马不是一天建成的:成功的架构是逐步完善的,不应期望一步到位。
    • 冰山下面才是关键:业务需求和场景是推动技术创新的关键,而不是单纯的技术追求。
  • 简单原则
    • 简单优于复杂:在满足需求的前提下,选择最简单的方案。
    • 结构的复杂性:组件越多,系统越容易出故障,维护成本越高。
    • 逻辑的复杂性:单个组件承担过多功能或使用复杂算法,会导致系统难以维护和扩展。
    • KISS原则:保持系统简单,易于理解和维护。
  • 演化原则
    • 演化优于一步到位:软件架构需要根据业务发展不断变化,不应追求一次性设计完美架构。
    • 生物进化类比:架构设计类似于生物进化,通过不断迭代和优化来适应环境变化。
    • 快速落地:设计出满足当前业务需求的架构,快速落地并根据实际运行情况进行调整。
    • 避免过度设计:过度设计不仅浪费资源,而且往往不符合未来的实际需求。

4、复杂度来源:高性能

(1)高性能带来的复杂度
  • 单台计算机内部的复杂度:
    • 操作系统:操作系统是软件系统的运行环境,其复杂度直接影响软件系统的复杂度。
    • 进程和线程:进程和线程的引入是为了提高多任务处理的性能,但同时也增加了系统的复杂度。
    • 多核和多线程:SMP(对称多处理器结构)、NUMA(非一致存储访问结构)、MPP(海量并行处理结构)等技术用于实现真正的多任务并行处理。
  • 多台计算机集群的复杂度:
    • 任务分配:通过增加机器来提升性能,但任务分配器本身也会成为性能瓶颈。
- 任务分解:将复杂的业务系统拆分为多个子系统,每个子系统处理特定的任务,可以提高整体性能。
- 系统间的调用:系统拆分过细会导致系统间的调用次数增加,性能反而下降。
(2)高性能的技术手段
  • 单机性能优化:
    • 多线程:利用多线程并行处理任务。
    • 批量处理:减少I/O操作,提高处理效率。
    • 缓存:将计算结果缓存起来,减少重复计算。
  • 集群性能优化:
    • 任务分配器:选择合适的任务分配器(硬件网络设备、软件网络设备、负载均衡软件等)。
    • 任务分解:将业务系统拆分为多个子系统,每个子系统处理特定的任务。
    • 数据一致性:使用BASE原理和最终一致性来保证分布式系统中的数据一致性。
(3)实践中的挑战
  • 任务分配的复杂性:
    • 连接管理:管理任务分配器和业务服务器之间的连接。
    • 分配算法:选择合适的任务分配算法(轮询、按权重分配、按负载分配等)。
    • 状态管理:管理和监控多台机器的状态。
  • 任务分解的复杂性:
    • 系统间的调用:系统拆分过细会导致系统间的调用次数增加,性能下降。
    • 性能优化:针对有瓶颈的子系统进行性能优化,而不是改动整个系统。
    • 粒度控制:合理控制系统拆分的粒度,避免过度拆分。
(4)实际案例
  • 微信后台架构:
    • 任务分解:将业务系统拆分为接入、注册登录、消息、LBS、摇一摇、漂流瓶等子系统。
    • 性能提升:通过任务分解,更容易发现和优化性能瓶颈。
  • 大数据处理:
    • 压缩:减少数据传输量。
    • 合并:将多个数据合并为一个数据。
    • 采样:使用采样数据进行统计,降低对精确性的要求。

5、复杂度来源:高可用

(1)高可用的定义
  • 无中断:系统在任何情况下都能无中断地执行其功能。
  • 难点:无论是硬件还是软件,都无法做到绝对无中断,外部环境(如断电、自然灾害)更是不可控的。
(2)高可用的实现方式
  • 冗余:通过增加冗余的机器、机房、网络通道等来实现高可用。
  • 与高性能的区别:
    • 高性能:增加机器目的是扩展处理性能。
    • 高可用:增加机器目的是冗余处理单元。
(3)计算高可用
  • 特点:计算结果在不同机器上是一致的,迁移计算对业务影响不大。
  • 复杂度:主要体现在任务分配和状态决策上。
(4)存储高可用难点
  • 数据传输延迟:不同机房间的数据传输速度慢,导致数据不一致。
  • 传输线路故障:线路可能中断、拥塞或异常,影响数据同步。
  • CAP定理:存储高可用不可能同时满足一致性、可用性和分区容错性,最多满足其中两个。
(5)高可用状态决策
  • 独裁式:存在单一决策者,但决策者本身可能故障。
  • 协商式:两个个体通过交流信息进行决策,但连接中断可能导致决策混乱。
  • 民主式:多个个体通过投票决策,但可能产生脑裂问题。

6、复杂度来源:高扩展

(1)定义
  • 可扩展性是指系统为了应对将来需求变化而提供的扩展能力。当有新的需求出现时,系统不需要或者仅需要少量修改就可以支持,无须整个系统重构或者重建。
(2)重要性
  • 软件系统的多变性:新的需求总会不断提出来,因此可扩展性显得尤为重要。
  • 技术发展:面向对象思想和设计模式的提出和发展,都是为了解决可扩展性问题。
(3)预测变化
  • 设计可扩展性系统的两个基本条件
    • 正确预测变化:预测未来的业务需求和技术变化。
    • 完美封装变化:将变化的部分与稳定的部分分离,使系统能够灵活应对变化。
  • 预测变化的复杂性
    • 预测的难度:预测变化是一项复杂且没有通用标准的任务,依赖于架构师的经验和直觉。
    • 过度预测的风险:过度预测会导致架构设计过于庞大,难以落地。
    • 预测的不确定性:预测可能出错,导致前期投入的工作量白费。
(4)应对变化方案
  • 方案一:变化层和稳定层的分离
    • 变化层:封装可能变化的部分。
    • 稳定层:封装不变的部分。
    • 复杂性:需要明确哪些部分属于变化层,哪些部分属于稳定层,并设计合理的接口。
  • 方案二:抽象层和实现层的分离
    • 抽象层:定义稳定的接口和规则。
    • 实现层:根据具体业务需求实现具体的逻辑。
    • 复杂性:抽象层的设计需要非常谨慎,一旦确定就不易修改。
(5)设计模式的应用
  • 装饰者模式:通过装饰者模式,可以在不修改原有代码的情况下增加新的功能。
  • 复杂性:设计模式的使用增加了代码的复杂性,需要深入理解和应用。
(6)实际应用中的挑战
  • 过度设计:过度考虑可扩展性可能导致设计过于复杂,影响系统的可维护性和性能。
  • 适度设计:在设计时需要权衡可扩展性和实际需求,避免不必要的复杂性。

7、复杂度来源:低成本、安全、规模关键点总结

(1)低成本
  • 成本的重要性:当架构方案涉及大量服务器时,成本成为重要考虑因素。例如,节省2000台服务器每年可节省4000万元。
  • 低成本与高性能、高可用的冲突:低成本通常意味着减少服务器数量,这与高性能和高可用的要求相冲突。
  • 创新的重要性:达到低成本目标往往需要创新,包括引入或创造新技术。例如,NoSQL、全文搜索引擎、Hadoop等。
  • 中小型公司与大型公司的差异:中小型公司通常依赖引入新技术,而大型公司可能自己创造新技术。
(2)安全
  • 安全的重要性:安全问题对业务和企业形象影响巨大,常见的安全事件如信息泄露、DDoS攻击等。
  • 功能安全 vs 架构安全:
    • 功能安全:主要与编码相关,防止常见的攻击如XSS、CSRF、SQL注入等。
    • 架构安全:防止大规模攻击,如DDoS攻击。传统方法依赖防火墙,但互联网领域更多依赖运营商或云服务商的流量清洗能力。
  • 安全的复杂性:功能安全和架构安全都需要持续改进,无法一劳永逸地解决所有问题。
(3)规模
  • 规模带来的复杂度:系统功能和数据量的增加会导致复杂度指数级上升。
  • 功能复杂度:功能数量增加会导致功能之间的连接呈指数级增长,从而增加系统复杂度。
  • 数据复杂度:数据量增加可能导致传统数据处理手段失效,需要引入大数据技术。例如,MySQL单表数据量过大时需要拆分表,这会引入新的复杂性。

8、架构设计原则案例

(1)架构设计的核心原则
  • 合适原则:优先满足业务需求,选择最适合当前业务的技术方案。
  • 简单原则:挑选简单方案快速落地验证,避免过度设计。
  • 演化原则:随着业务发展,逐步调整和优化架构,避免一次性设计过于复杂。
(2)淘宝的架构发展历程
  • 个人网站阶段:初期追求快速上线,选择轻量级、简单的系统。
  • Oracle/支付宝/旺旺阶段:业务快速发展,通过购买高性能的 Oracle 和存储设备来支撑。
  • Java 时代 1.0:技术问题影响业务,通过重构和切换到 Java 来解决。
  • Java 时代 2.0:进行大量优化,包括数据分库、放弃 EJB、引入 Spring、加入缓存等。
  • Java 时代 3.0 和分布式时代:业务规模急剧上升,通过自研系统降低 IOE 成本,实现分布式架构。
(3)手机 QQ 的架构发展历程
  • 十万级 IM 1.X:初期架构简单,追求快速上线。
  • 百万级 IM 2.X:业务发展到百万级用户,进行架构改造,解决性能和扩展性问题。
  • 千万级 IM 3.X:业务发展到千万级用户,进一步优化架构,解决内存、CPU、网卡等瓶颈。
  • 亿级 IM 4.X:业务发展到亿级用户,原有架构难以支撑,重新设计实现新的架构,包括存储架构和通信架构。
(4)架构设计的实践要点
  • 快速迭代:初期追求快速上线,满足业务需求。
  • 逐步优化:随着业务发展,逐步优化和调整架构。
  • 适度预测:适当预测业务发展,但避免过度设计。
  • 成本控制:随着业务规模的扩大,成本控制变得重要。
  • 技术选型:选择适合当前业务的技术方案,避免盲目追求新技术。

9、架构设计流程:识别复杂度

(1)识别复杂度的方法
  • 排查法:从不同的角度逐一分析系统的复杂性,例如业务逻辑、功能耦合、性能需求等。
  • 经验判断:有经验的架构师可以通过对需求的理解,快速识别出主要的复杂性问题。
  • 数据计算:通过计算系统的TPS(每秒事务处理数)和QPS(每秒查询数),评估系统的性能需求。
(2)优先级排序
  • 根据业务和技术综合判断:在识别出复杂度后,需要根据业务需求、技术现状和团队能力进行优先级排序,优先解决当前最紧迫的问题。
  • 逐步解决问题:不要试图一次性解决所有问题,而是逐步推进,每次解决一个主要问题后再逐步优化其他问题。
(3)实战案例:"前浪微博"
  • 业务背景:前浪微博业务快速发展,系统间协作效率低,存在多个子系统之间的强耦合问题。
  • 复杂度分析:
    • 高性能:消息队列需要处理高QPS的读取请求。
    • 高可用:消息队列需要保证消息的高可用性,包括写入、存储和读取。
    • 可扩展:虽然当前不需要高度扩展,但需要预留一定的性能余量以应对未来业务增长。
(4)具体设计目标
  • TPS和QPS:根据业务规模计算出的TPS为1380,QPS为13800,这是设计目标的峰值4倍。
  • 系统容量:预留一定的系统容量以应对未来业务的增长,但一般不超过10倍。
(5)架构师的技能要求
  • 技术:掌握常见的系统性能指标和架构设计原则。
  • 沟通:能够与团队成员有效沟通,推动项目进展。
  • 推动:有能力推动项目的实施,解决项目中的各种问题。
  • 管理:具备项目管理和团队管理的能力。
  • 撕逼:在必要时能够说服他人接受自己的设计方案。

10、架构设计流程:设计备选方案

(1)设计备选方案
  • 目标明确:在识别复杂度后,明确架构设计的目标,开始设计备选方案。
  • 技术组合:成熟的架构师通常基于已有的技术和架构模式进行组合和调整,而不是从零开始创新。
  • 常见错误:
    • 追求最优方案:设计最优秀的方案往往不符合实际需求,导致资源浪费或无法实现。
    • 单一方案:只设计一个方案可能导致思维狭隘,忽略其他可能更好的方案。
    • 方案过于详细:备选方案阶段应关注技术选型,而非技术细节。
(2)设计备选方案的原则
  • 数量合理:备选方案数量以3~5个为最佳,少于3个可能考虑不周全,多于5个则耗费过多精力。
  • 差异明显:备选方案之间应有明显的差异,避免仅在细节上有所不同。
  • 视野开阔:不要局限于已熟悉的技术,考虑更多可能性。
(3)实战案例:前浪微博消息队列设计
  • 备选方案1:采用开源的Kafka
    • 优点:功能强大,性能高,成熟度高,已被广泛使用。
  • 备选方案2:集群 + MySQL 存储
    • 高性能读取:基于Netty开发,采用集群方式。
    • 高可用写入:集群方式,轮询算法。
    • 高可用存储:利用MySQL主备复制。
    • 高可用读取:主备方案。
  • 备选方案3:集群 + 自研存储方案
    • 存储优化:自研文件存储和复制方案,更契合消息队列的数据特点。
  • 备选方案 4:分散集群
    • 采用数据分散集群的架构,集群中的服务器进行分组,每个分组存储一部分消息数据,主备数据复制,分组间数据不同步。客户端采取轮询策略写入和读取消息。

11、架构设计流程:评选备选方案

(1)评估和选择备选方案的重要性
  • 每个方案都是可行的:如果方案不可行,就不应该作为备选方案。
  • 没有完美方案:每个方案都有优缺点,例如性能、成本、新技术风险等。
  • 评价标准主观性强:不同设计师对复杂度等概念的理解不同,容易引发争议。
(2)常见的指导思想
  • 最简派:选择最简单的方案,例如基于 MySQL 的全文搜索。
  • 最牛派:选择技术上最牛的方案,例如 Redis 相比 Memcache。
  • 最熟派:选择最熟悉的方案,例如继续使用 C++。
  • 领导派:让领导来定夺,避免自己承担责任。
(3)评估和选择备选方案的方法
  • 360 度环评:列出需要关注的质量属性点,从多个维度评估每个方案,综合挑选最优方案。
  • 常见质量属性点:性能、可用性、硬件成本、项目投入、复杂度、安全性、可扩展性等。
  • 遵循架构设计原则:
    • 合适原则:满足一定时期内业务发展的需求即可。
    • 简单原则:避免过度设计。
    • 演化原则:允许逐步演进,避免一步到位。
(4)实战案例:"前浪微博"消息队列系统
  • 备选方案 1:采用开源 Kafka 方案
    • 优点:成熟、节省开发投入。
    • 缺点:运维复杂、不适应业务需求。
  • 备选方案 2:集群 + MySQL 存储
    • 优点:复杂度不高、融入现有运维体系、可靠性有保障。
    • 缺点:性能一般、成本较高。
  • 备选方案 3:集群 + 自研存储系统
    • 优点:展现技术实力、性能高。
    • 缺点:复杂度高、开发周期长、运维难度大。
  • 最终选择备选方案 2:
    • 可运维性:Kafka 运维复杂,无法快速解决问题。
    • 复杂度:团队技术实力和人员规模无法支撑自研存储系统。
    • 性能:当前业务需求不高,方案 2 能满足,且可扩展。
    • 成本:虽然成本较高,但可以通过并行部署减少实际投入。

12、架构设计流程:方案详细设计

(1)详细方案设计的重要性
  • 定义:详细方案设计是将备选方案中的关键技术细节确定下来,使其成为一个可以落地的设计方案。
  • 难点:虽然备选方案的选择是最难的部分,但详细方案设计同样重要,因为它决定了方案的具体实现细节。
(2)技术细节的确定
  • Elasticsearch 示例:
    • 索引设计:按业务划分还是一个大索引。
    • 副本数量:2 个、3 个还是 4 个。
    • 集群节点数量:3 个还是 6 个。
  • Nginx 负载均衡策略:
    • 轮询:每个请求按时间顺序逐一分配。
    • 加权轮询:根据权重分配请求。
    • ip_hash:按访问 IP 的 hash 结果分配。
    • fair:按响应时间分配。
    • url_hash:按 URL 的 hash 结果分配。
(3)可能遇到的问题
  • 备选方案不可行:详细设计阶段可能会发现备选方案存在遗漏的关键技术点或质量属性。
  • 解决方案:
    • 详细评估每个技术点。
    • 考虑开发周期等质量属性。
    • 适时调整项目目标和计划。
(4)详细设计方案的实战
  • 数据库表设计:
    • 日志表:用于快速存储消息。
    • 消息表:每个消息队列一张表。
  • 数据复制:
    • 使用 MySQL 主从复制,只复制消息存储表。
  • 主备服务器倒换:
    • 使用 ZooKeeper 进行主备决策。
  • 业务服务器写入和读取消息:
    • 写入:先写日志表,再由后台线程写入消息表。
    • 读取:从消息表中读取。
  • 通信协议设计:
    • 使用 TCP 协议,数据格式为 ProtocolBuffer。
(5)避免"PPT 架构师"
  • 特点:
    • 不亲自写代码。
    • 对技术原理理解不深。
    • 方案设计缺乏细节,容易出现坑。
  • 建议:
    • 架构师需深入理解所选技术的原理、优缺点。
    • 实际操作和验证技术方案。
    • 降低方案复杂度,防止细节推翻整个方案。
相关推荐
李宥小哥40 分钟前
架构13-持久化存储
架构
李宥小哥7 小时前
架构实践04-高扩展架构模式
架构
吃滑椒的喵酱7 小时前
Apache Doris 开源最顶级基于MPP架构的高性能实时分析数据库
架构·开源·apache
东软吴彦祖8 小时前
实现基于分布式的LAMP架构+NFS实时同步到备份服务器
linux·运维·服务器·mysql·架构·wordpress
大明湖的狗凯.12 小时前
Servlet、omcat服务器架构与工作原理
服务器·servlet·架构
HsuYang17 小时前
Rollup源码学习(六)——重识Rollup构建生命周期
前端·javascript·架构
码农老起18 小时前
从阿里云EDM到美团云:典型微服务治理平台的实战经验分享
微服务·云原生·架构
颯沓如流星20 小时前
Java内存回收(GC)新贵的抉择,G1与ZGC!
java·jvm·架构
李宥小哥21 小时前
架构14-资源与调度
算法·贪心算法·架构