架构设计 - 面试题库
一、基础题 ⭐
Q1. 请解释单例模式的双重检查锁定实现
答案:双重检查锁定(DCL)在单例模式中用于延迟初始化且保证线程安全。实现时先检查实例是否为null,若为null则进入同步块,再次检查实例是否为null,若仍为null则创建实例。关键在于使用volatile关键字修饰实例变量,防止指令重排序导致其他线程获取到未完全初始化的对象。在Java中,volatile保证了可见性和有序性,使得DCL在JDK 5及之后版本能够正确工作。 关联知识点:设计模式、线程安全、volatile语义
Q2. 工厂模式与抽象工厂模式的区别是什么?
答案:工厂模式提供一个创建对象的接口,子类决定实例化哪个具体类,适用于创建单一等级结构的产品。抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,无需指定具体类,适用于创建多个产品族。简言之,工厂模式关注单个产品的创建,抽象工厂模式关注产品族的创建。抽象工厂模式的扩展性更好,新增产品族时无需修改现有代码,符合开闭原则。 关联知识点:创建型模式、开闭原则、产品族概念
Q3. 什么是MVC架构模式?各层职责是什么?
答案:MVC(Model-View-Controller)将应用分为三层:Model负责业务逻辑和数据存储,处理数据状态变化;View负责数据展示,将Model数据渲染给用户;Controller负责接收用户输入,协调Model和View的交互。用户操作触发Controller,Controller更新Model,Model变化通知View刷新。这种分离使得各层可独立开发和测试,提高了代码的可维护性和复用性。现代Web框架如Spring MVC、Django均基于此模式。 关联知识点:架构模式、关注点分离、Web框架设计
Q4. 观察者模式的应用场景和实现要点是什么?
答案:观察者模式定义对象间一对多的依赖关系,当被观察者状态改变时,所有观察者自动收到通知。典型应用包括事件监听器、消息订阅系统、响应式编程。实现要点:定义Subject接口维护观察者列表并提供注册/注销/通知方法;定义Observer接口定义更新方法;Subject状态变化时遍历调用观察者的更新方法。需注意避免循环依赖,通知顺序的不确定性,以及观察者执行耗时操作阻塞通知链的问题。 关联知识点:行为型模式、事件驱动、发布订阅
Q5. 什么是RESTful API?核心设计原则有哪些?
答案:RESTful API是基于REST(Representational State Transfer)架构风格的API设计。核心原则包括:资源用名词标识,通过URI定位;使用HTTP方法表达操作(GET查询、POST创建、PUT更新、DELETE删除);无状态设计,每次请求包含完整上下文;统一接口,标准化资源表示和交互方式;支持HATEOAS,响应中包含相关操作链接。RESTful API的优势在于简洁、可缓存、可伸缩,是现代Web API的主流设计风格。 关联知识点:API设计、HTTP协议、无状态架构
Q6. 分层架构与微服务架构的核心区别是什么?
答案:分层架构将系统按技术职责划分为表现层、业务层、数据层等,各层部署在同一进程中,通过函数调用通信,是单体应用的典型结构。微服务架构按业务领域拆分服务,每个服务独立部署、拥有独立数据存储,服务间通过网络通信。分层架构的优势是开发简单、调试方便,但扩展性受限;微服务架构的优势是独立扩展、技术栈灵活、团队自治,但引入了分布式系统的复杂性。 关联知识点:架构演进、单体架构、服务拆分
Q7. 什么是CAP定理?在分布式系统中如何取舍?
答案:CAP定理指出分布式系统无法同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance)三个特性,最多只能同时满足两个。分区容错性是分布式系统的必选项,因此实际取舍在CP和AP之间。CP系统如ZooKeeper、HBase,在分区时保证一致性但牺牲可用性;AP系统如Cassandra、DynamoDB,在分区时保证可用性但牺牲强一致性。现代系统多采用BASE理论,追求最终一致性。 关联知识点:分布式理论、一致性模型、系统权衡
Q8. 策略模式的适用场景和优势是什么?
答案:策略模式定义一系列算法,将它们封装成独立的策略类,使它们可以互相替换。适用场景包括:同一操作有多种实现方式(如排序算法、支付渠道、压缩算法);需要在运行时动态切换算法;避免使用大量条件语句。优势在于符合开闭原则,新增策略无需修改上下文类;算法可独立测试和维护;消除了条件分支带来的耦合。缺点是客户端需要了解所有策略类,增加了使用复杂度。 关联知识点:行为型模式、开闭原则、消除条件分支
二、进阶题 ⭐⭐
Q9. 装饰器模式与继承的区别?何时使用装饰器?
答案:继承是静态的,在编译期确定行为,会导致类爆炸;装饰器模式是动态的,在运行期组合行为,更灵活。装饰器模式通过包装对象来添加职责,不修改原有类结构,符合组合优于继承原则。适用场景:需要动态添加/撤销职责,如Java I/O流中的BufferedInputStream包装FileInputStream;继承关系过深导致类爆炸;不同职责的组合方式多样,无法通过继承穷举。装饰器的缺点是调试困难,包装层次不直观。 关联知识点:结构型模式、组合优于继承、动态职责添加
Q10. 依赖倒置原则(DIP)如何指导架构设计?
答案:依赖倒置原则要求高层模块不依赖低层模块,两者都依赖抽象;抽象不依赖细节,细节依赖抽象。在架构设计中,这意味着业务逻辑不应依赖具体实现,而应依赖接口。例如,业务层定义仓储接口,数据层实现该接口,而非业务层直接调用ORM。DIP是实现插件化架构和可测试架构的基础,使得模块可替换、可Mock。结合依赖注入容器,可以实现模块间的松耦合,是六边形架构和整洁架构的核心原则。 关联知识点:SOLID原则、依赖注入、松耦合设计
Q11. 什么是六边形架构(端口与适配器)?解决了什么问题?
答案:六边形架构将应用分为内部业务逻辑(核心)和外部交互接口(适配器),通过端口(接口)连接。核心完全不依赖外部技术,外部技术通过适配器适配到端口。这解决了传统分层架构中业务逻辑与技术框架耦合的问题。优势:业务逻辑可独立测试,无需数据库、消息队列等基础设施;技术栈可替换而不影响核心逻辑;支持多种输入输出通道(HTTP、CLI、消息)。实现关键是依赖方向:外部依赖内部,内部不依赖外部。 关联知识点:架构模式、关注点分离、可测试性设计
Q12. 代理模式有哪些类型?各自的应用场景是什么?
答案:代理模式为对象提供代理以控制访问。主要类型:远程代理(如RPC客户端,隐藏远程调用细节);虚拟代理(延迟加载大对象,如图片懒加载);保护代理(控制访问权限,如权限校验);智能代理(附加逻辑,如缓存、日志)。Spring AOP基于动态代理实现,可在方法执行前后插入横切逻辑。代理模式的核心价值是解耦核心业务与横切关注点,但过度使用会增加调试难度和性能开销。 关联知识点:结构型模式、AOP、动态代理、横切关注点
Q13. 事件驱动架构的优势和挑战是什么?
答案:事件驱动架构通过事件的发布和订阅实现组件间通信。优势:解耦生产者与消费者,双方无需知道彼此存在;异步处理提高响应速度;易于扩展新消费者而不影响现有逻辑;支持事件溯源和审计。挑战:事件顺序保证困难,需要引入序列号或逻辑时钟;调试和追踪复杂,调用链不直观;事件格式变更需要版本管理;可能出现事件丢失或重复消费,需要幂等处理。典型实现包括Kafka、RabbitMQ等消息中间件。 关联知识点:异步架构、消息中间件、事件溯源
Q14. 什么是CQRS模式?何时应该使用?
答案:CQRS(Command Query Responsibility Segregation)将读写操作分离,使用不同的模型处理命令(写)和查询(读)。写模型关注业务规则和一致性,读模型针对查询优化,可使用不同的数据结构甚至不同的数据库。适用场景:读写负载差异大,读远多于写;需要多种视图展示同一数据;团队协作中读写由不同团队负责。不建议在简单CRUD场景使用,会增加系统复杂度。常与事件溯源结合使用。 关联知识点:架构模式、读写分离、事件溯源
Q15. 分布式系统中如何实现全局唯一ID?
答案:常见方案:UUID简单但无序且占用空间大;数据库自增ID单点瓶颈明显;雪花算法(Snowflake)是主流方案,由时间戳+机器ID+序列号组成,生成分布式有序ID,性能高且不依赖外部系统。改进方案包括美团Leaf(支持号段和雪花模式)、百度UidGenerator(基于缓存行优化)。选择时需考虑:是否需要趋势递增、是否需要业务含义、并发量级、容灾要求。雪花算法的时钟回拨问题需要特殊处理。 关联知识点:分布式ID、Snowflake算法、时钟同步
Q16. 什么是服务网格(Service Mesh)?解决了微服务的什么问题?
答案:服务网格是基础设施层,处理服务间通信,典型实现如Istio+Envoy。它将服务治理功能(负载均衡、熔断、限流、服务发现、可观测性)从业务代码中抽离,以Sidecar代理形式部署。解决的问题:多语言微服务需要重复实现治理逻辑;治理逻辑与业务逻辑耦合,升级困难;跨团队治理标准不统一。优势是业务代码更纯粹、治理能力统一升级、支持异构技术栈。代价是增加网络延迟和资源消耗。 关联知识点:微服务架构、Sidecar模式、基础设施下沉
三、高级题 ⭐⭐⭐
Q17. 如何设计一个高可用的分布式缓存系统?
答案:高可用缓存设计需考虑:数据分片,使用一致性Hash将数据分布到多节点,减少节点变化时的数据迁移;副本机制,主从复制或集群模式保证单点故障不影响服务;缓存穿透防护,使用布隆过滤器或缓存空值;缓存雪崩防护,设置随机过期时间避免集中失效;缓存击穿防护,使用分布式锁保证单线程回源;多级缓存架构,本地缓存+分布式缓存降低延迟;持久化机制,RDB/AOF保证数据不丢失。典型方案如Redis Cluster。 关联知识点:缓存架构、一致性Hash、高可用设计
Q18. 分布式事务有哪些解决方案?各自的适用场景?
答案:2PC(两阶段提交)强一致性,但性能差、阻塞协议,适用于银行等强一致场景;TCC(Try-Confirm-Cancel)业务侵入性强,性能好,适用于金融核心系统;本地消息表最终一致性,实现简单,适用于对一致性要求不极端的场景;Saga模式将长事务拆分为多个本地事务,通过补偿操作回滚,适用于长流程业务;可靠消息最终一致性,通过消息中间件保证,适用于异步解耦场景。选择依据:一致性要求、性能要求、业务侵入性容忍度。 关联知识点:分布式事务、最终一致性、Saga模式
Q19. 如何设计一个支持百万并发的系统架构?
答案:百万并发架构需要多层优化:接入层使用CDN+DNS负载均衡分发请求;网关层使用Nginx/Envoy做限流和路由;应用层无状态设计,水平扩展,使用连接池复用资源;缓存层多级缓存,热点数据本地缓存,一般数据分布式缓存;数据层分库分表,读写分离,使用NoSQL处理特定场景;异步化,非核心链路异步处理,削峰填谷;降级策略,非核心功能可降级,保证核心链路可用。关键是识别瓶颈、消除单点、容量规划。 关联知识点:高并发架构、负载均衡、容量规划
Q20. 什么是领域驱动设计(DDD)?核心概念有哪些?
答案:DDD是一种以业务领域为核心的软件设计方法。核心概念:实体(有唯一标识和生命周期)、值对象(无标识,由属性定义)、聚合(一致性边界内的实体集合)、领域服务(不属于任何实体的业务逻辑)、仓储(聚合持久化抽象)、领域事件(领域内发生的重要事情)。DDD通过统一语言消除沟通鸿沟,通过限界上下文划分模块边界。战略设计关注上下文映射和模块划分,战术设计关注领域模型实现。适用于业务复杂、需求频繁变化的系统。 关联知识点:领域建模、限界上下文、复杂业务设计
Q21. 如何设计一个可扩展的插件化架构?
答案:插件化架构核心是定义稳定的扩展点(SPI),实现可插拔。设计要点:定义清晰的接口契约,插件通过实现接口扩展功能;使用依赖注入容器管理插件生命周期;插件隔离,每个插件独立类加载器避免冲突;版本兼容,接口变更需向后兼容或提供迁移策略;插件发现机制,通过配置文件或自动扫描注册;沙箱机制限制插件权限保证安全。Java的SPI机制、OSGi、Eclipse插件系统都是典型实现。关键挑战是接口设计的稳定性和版本管理。 关联知识点:SPI机制、依赖注入、版本管理
Q22. 微服务拆分的原则和常见陷阱是什么?
答案:拆分原则:单一职责,每个服务聚焦一个业务能力;高内聚低耦合,服务内强相关,服务间弱依赖;数据自治,每个服务拥有独立数据存储;团队对齐,服务边界与团队边界一致(康威定律);渐进式拆分,从单体中逐步剥离,避免大爆炸。常见陷阱:过度拆分导致分布式单体,服务间调用链过长;共享数据库导致紧耦合;服务粒度太小,运维成本超过收益;忽略分布式事务和一致性;服务间同步调用过多,级联故障风险。 关联知识点:微服务拆分、康威定律、分布式单体
Q23. 如何设计一个支持多租户的SaaS架构?
答案:多租户架构有三种数据隔离模式:独立数据库,隔离性最好但成本高,适用于金融等敏感场景;共享数据库独立Schema,平衡成本和隔离,适用于中型租户;共享数据库共享Schema,成本最低但隔离最差,需通过tenant_id区分数据,适用于海量小租户。设计要点:租户识别(域名、Header、Token);数据隔离保证;租户级别的功能开关和资源配额;计费系统对接;数据迁移和备份策略。关键挑战是隔离性与成本的平衡。 关联知识点:SaaS架构、数据隔离、多租户设计
Q24. 什么是混沌工程?如何在生产环境中实施?
答案:混沌工程是通过主动注入故障来验证系统韧性的实践。实施步骤:定义稳态指标(如延迟、错误率),作为系统正常的基线;提出假设(如”节点宕机不影响服务”);在生产环境注入故障(网络延迟、CPU满载、进程杀死);观察稳态指标是否偏离;修复发现的问题。工具包括ChaosBlade、Gremlin、Litmus。实施原则:从小范围开始,逐步扩大爆炸半径;有回滚预案;监控覆盖完整;在非高峰时段执行。目标是发现隐藏的脆弱性。 关联知识点:系统韧性、故障注入、生产验证
Q25. 如何设计一个分布式系统的可观测性方案?
答案:可观测性包含三大支柱:日志(Logs)记录离散事件,用于问题定位,需结构化存储和集中管理(ELK);指标(Metrics)聚合数据反映系统状态,用于监控告警(Prometheus+Grafana);链路追踪(Traces)记录请求完整路径,用于性能分析(Jaeger、SkyWalking)。设计要点:统一TraceID贯穿全链路;采样策略平衡开销和覆盖率;日志与链路关联;指标分层(业务、应用、基础设施);告警规则基于SLO。关键是数据关联性和查询效率。 关联知识点:可观测性、分布式追踪、SLO
Q26. 什么是整洁架构(Clean Architecture)?与六边形架构的区别?
答案:整洁架构由Robert C. Martin提出,将系统分为同心圆层:实体层(业务规则)、用例层(应用逻辑)、接口适配器层(数据转换)、框架层(外部依赖)。依赖规则:内层不依赖外层,依赖方向指向圆心。与六边形架构的核心思想一致(依赖倒置),但整洁架构更强调层次划分和依赖方向,六边形架构更强调端口与适配器的概念。两者都旨在使业务逻辑独立于框架和外部服务,提高可测试性和可维护性。 关联知识点:架构设计、依赖规则、可测试性
Q27. 如何设计一个支持灰度发布的系统?
答案:灰度发布(金丝雀发布)逐步将流量从旧版本切换到新版本。设计要点:流量路由,基于用户ID、地域、设备特征等维度路由到不同版本;比例控制,支持按百分比逐步放量;快速回滚,发现问题时一键切回旧版本;数据兼容,新旧版本数据结构向前兼容;监控对比,实时对比新旧版本的核心指标;自动化决策,基于指标自动判断是否继续发布。实现方式包括网关层路由规则、服务注册中心权重配置、客户端负载均衡策略。 关联知识点:发布策略、流量治理、版本兼容
Q28. 分布式锁的实现方案有哪些?各自的优缺点?
答案:基于数据库:实现简单但性能差,存在单点瓶颈;基于Redis(SETNX+过期时间):性能好,但Redlock算法在时钟跳跃时可能失效,适用于非关键场景;基于ZooKeeper(临时顺序节点):强一致性,可靠性高,但性能不如Redis,适用于金融等强一致场景;基于etcd(Lease机制):类似ZK但更轻量。选择依据:一致性要求、性能要求、已有基础设施。注意锁的超时设置、可重入性、续期机制(WatchDog)和死锁预防。 关联知识点:分布式锁、Redis、ZooKeeper、etcd
Q29. 如何设计一个事件溯源(Event Sourcing)系统?
答案:事件溯源将状态变更存储为事件序列,而非当前状态。设计要点:事件不可变,一旦写入不可修改或删除;事件设计包含足够信息重建状态,使用过去时态命名(OrderCreated);快照机制,定期保存当前状态避免全量重放;事件版本管理,支持事件结构演进;投影(Projection)从事件派生出查询视图;命令验证确保事件合法性。优势是完整审计、时间旅行、自然的事件驱动;挑战是学习曲线陡峭、查询复杂度增加、事件迁移困难。 关联知识点:事件溯源、CQRS、审计日志
Q30. 架构演进过程中,如何从单体迁移到微服务?
答案:迁移策略:绞杀者模式(Strangler Fig),在单体前加代理,逐步将功能迁移到新服务,最终替代单体;并行运行,新旧系统同时运行,通过数据同步保持一致,验证后切换;分支抽象,从单体中提取模块为独立服务,逐步解耦。关键步骤:识别边界,基于业务领域划分服务;数据迁移,双写或CDC同步;流量切换,灰度验证;回滚预案。避免大爆炸式重写。迁移过程中保持单体可发布,每次迁移一个小功能,持续交付。 关联知识点:架构演进、绞杀者模式、数据迁移