分布式系统架构面试题汇总(上)

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
传统型负载均衡 CLB,每月750个小时 15LCU
简介: 这篇文章主要是说在进化的过程中可能会遇到的问题以及如何去解救这些问题。

一、客户端缓存优化


1、添加CDN缓存


CDN 缓存也叫作网络访问的“第一跳”,用户请求先到达的是互联网网络服务商的机房。在机房里面部署 CDN 服务器,提供缓存服务。缓存了一些静态资源。如果存在用户请求的内容,直接通过CDN进行返回;没有的话继续向下请求

v2-3f624127bfaf13a739ce69bfc4fde5d0_1440w.jpg

2、正向代理缓存


正向代理缓存保存在客户端,代理客户端访问互联网,比如访问谷歌,直接访问不到,我们就可以使用一个代理服务器,将请求转发给代理服务器,代理服务器能够访问谷歌,这样由代理去谷歌取到返回数据,再返回给我们。

v2-c5de01a20393bc335fd8aa3b8621b167_1440w.jpg

既然正向代理服务器可以取得谷歌的数据,他就可以缓存这些数据同时记录下客户端身份,当下次请求的时候通过客户端身份验证,就可以直接找到这些缓存的数据了。


3、反向代理缓存


反向代理是在服务器这一端的,用户通过互联网连接到数据中心的时候,连接的通常是一个反向代理服务器,反向代理服务器根据用户的请求,在本地的反向代理缓存中查找是否有用户请求的数据,如果有就直接返回这个数据,如果没有再把这个请求向下继续转发。

v2-176f1864d36734539877f4b6f46e62f0_1440w.jpg

二、服务端优化


1、应用程序分布式部署


分布式部署的意思是同一个应用程序分布在不同的服务器上,一块对外提供服务。他们之间的等位相等。


(1)负载均衡算法访问不同应用程序,避免单一应用程序的压力


客户端通过反向代理执行负载均衡算法去访问不同的应用程序

①随机均衡算法 ②多权重负载 ③session 粘连


(2)不同的应用程序其实是同一个,如何解决session问题


注意,不同功能的应用程序也要解决session功能,


第一种:粘性session


原理:粘性Session是指将用户锁定到某一个服务器上,比如,用户第一次请求时,负载均衡器将用户的请求转发到了A服务器上,第二次访问时,反向代理根据sessionID通过hash算法,转发到A服务器上。

v2-f01f1c3bb0700afaadcd23029cfb1332_1440w.jpg

缺点:缺乏容错性,如果当前访问的服务器发生故障,用户被转移到第二个服务器上时,他的session信息都将失效。


第二种:session同步


原理:任何一个服务器上的session发生改变(增删改),会广播给所有其它节点,不管其他服务器需不需要session,以此来保证Session同步。

v2-a1251561e90f00838a1c5792660ceea0_1440w.jpg

缺点:会对网络负荷造成一定压力,如果session量大的话可能会造成网络堵塞,拖慢服务器性能。


第三种:持久化到缓存数据库


原理:拿出一个缓存数据库,存储session信息,并设置相应的失效时间。每次访问的时候不管是负载到了哪一个服务器都会先从缓存数据库里面查询session


2、应用程序拆分成微服务


v2-e02549cb7fb35f8145f0df4e106e7bc0_1440w.jpg

(1)微服务的注册与发现Eureka


既然是微服务,就要有一个中心去管理,有了中心之后,我们就可以将各种服务往里面注册使得各个服务可以相互感知到。


Springcloud有一个Eureka注册与发现中心,保存了各个微服务的名称、IP地址、端口号等信息。这个时候,服务之间进行交流与交互。

一般注册中心会采取集群的策略,进行容错;


(2)微服务的通信


①Ribbon


本质是一个带有负载均衡功能的http客户端,在每次请求的时候会通过负载均衡算法Round Robin轮询算法选择一台机器,均匀的把请求分发到各台机器上。这是从每一个微服务搭建成了分布式的系统来考虑的。


实现原理:Ribbon会从 Eureka Client里获取到对应的服务注册表,也就知道了所有的服务都部署在了哪些机器上,在监听哪些端口号;然后Ribbon就可以使用默认的Round Robin算法,从中选择一台机器。


②Feign


两个不同的微服务就可以使用Feign来通信,Feign集成了Ribbon。底层使用的是动态代理的功能:


Feign的工作原理:


第一:对某个接口定义了@FeignClient注解,Feign就会针对这个接口创建一个动态代理;

第二:接着你要是调用那个接口,本质就是会调用 Feign创建的动态代理

第三:Feign的动态代理会根据你在接口上的@RequestMapping等注解,来动态构造出你要请求的服务的地址;

第四:Feign中的Ribbon拿到这个地址,通过负载均衡算法调用相应的微服务的相应方法;

(3)微服务的容错机制Hystrix


这个功能的微服务即使是搭建了集群可能也会出错,从而造成服务雪崩;Springcloud提供了熔断和服务降级的策略进行容错;


①降级


如果调用的远端服务出现问题(超时或异常),则返回一个结果,用于提示。一般都是返回一个默认值;


②熔断


如果调用的远端服务出现问题,则在一段时间之内直接返回提示信息(不再调远端的服务),一段时间后陆续调用远端服务,如果不再出现问题,则恢复正常调用远端服务。


(4)微服务的网关Zuul


这么多微服务部署在不同的服务器上地址是不一样的,可以通过网关Zuul把所有的服务接口统一起来暴露出去给客户用。在这里我们可以过滤用户的一些信息或者是做权限验证等等工作;


(5)微服务的属性配置SpringCloud Config


服务一多,改配置太麻烦了,需要有个东西来管理,最好还能在线修改配置,这时候分布式配置中心(Spring Cloud Config)就出现了,它实现了将所有服务的配置文件都抽取到一个统一的地方


(6)微服务消息总线Springcloud Bus


想要更改配置的时候,服务能够知道并且热更新配置,那么就需要一个消息传递工具——消息总线(Spring Cloud Bus),通过这个总线向其他服务传递消息


(7)微服务的链路追踪


我们想要知道各个服务之间的调用关系间接得到服务之间的依赖,那么就需要服务追踪组件(zipkin ,SpringCloud Sleuth集成了zipkin)了。


3、微服务会出现的问题


(1)Session问题:解决方式同上


(2)大规模的增删改查,如何抵抗住压力


①采用消息队列对用户访问进行削峰处理


②服务的熔断和降级策略


(3)分布式事务


比如:例如在下单场景下,库存和订单如果不在同一个节点上,涉及分布式事务。

分布式事务的最主要特点是需要跨节点进行通信,解决办法如下:


首先基于CAP理论,保证BASE特性。接下来看看如何解决:


①在设计微服务架构的时候尽可能的保证微服务的独立性。


②2pc协议模型


引入协调者(Coordinator)来协调参与者的行为,并最终决定这些参与者是否要真正执行事务。


第一阶段是表决阶段,所有参与者都将本事务能否成功的信息反馈发给协调者;


第二阶段是执行阶段,协调者根据所有参与者的反馈,通知所有参与者,步调一致地在所有分支上提交或者回滚。


2pc的缺点:


(1)第一阶段到第二阶段有一个时间差,时间太久了之后,第一节点的某些参与者可能不能成功执行事务了,但是之前告诉协调者说我可以成功发送,这就造成了错误。


(2)协调者在整个两阶段提交过程中扮演着举足轻重的作用,一旦协调者所在服务器宕机,那么就会影响整个数据库集群的正常运行,比如在第二阶段中,如果协调者因为故障不能正常发送事务提交或回滚通知,那么参与者们将一直处于阻塞状态,整个数据库集群将无法提供服务。


(3)同步阻塞:两阶段提交执行过程中,所有的参与者都需要听从协调者的统一调度,期间处于阻塞状态而不能从事其他操作,这样效率及其低下。


③基于消息队列的最终一致性方案


消息一致性方案是通过消息中间件保证上、下游应用数据操作的一致性。基本思路是将本地操作和发送消息放在一个事务中,保证本地操作和消息发送要么两者都成功或者都失败。下游应用向消息系统订阅该消息,收到消息后执行相应操作。

v2-24ab6ae0459fca64a3fdd3385ac88775_1440w.jpg

基本思路如下:


(1)将事务操作进行封装

(2)上游业务(订单服务)先执行事务操作,成功之后将数据发送到消息队列

(3)下游服务(库存服务)监听消息队列,然后去执行,执行成功或者是失败都通过ACK告诉上游业务,上游业务根据这个ACK信息决定是否回滚或提交。

但是可能会出现异常的情况:


(1)直接无法到达消息队列


网络断了,抛出异常,上游业务直接回滚即可。


(2)消息已经到达消息队列,但返回的时候出现异常


MQ提供了确认ack机制,可以用来确认消息是否有返回。因此我们可以在发送前在数据库中先存一下消息,如果ack异常则进行重发


(3)消息送达后,消息服务自己挂了


先操作数据库,然后再往消息队列发送


(4)未送达消费者


消息队列收到消息后,消费者去消费,此时消息队列会处于"UNACK"的状态,直到客户端确认消息


(5)确认消息丢失


消息返回时假设确认消息丢失了,那么消息队列认为消息没有到达消费者会重发消息。


(6)消费者业务处理异常


消费者接受消息并处理,假设抛异常了,先重试,重试到一定的次数之后进行返回事务执行失败。


(7)分布式锁


关于分布式锁的设计,从以下四个角度考虑:


第一:互斥性。在任意时刻,只有一个客户端能持有锁。

第二:不会发生死锁。即使有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁。

第三:具有容错性。只要大部分的节点正常运行,客户端就可以加锁和解锁。

第四:加锁和解锁必须是同一个客户端,客户端自己不能把别人加的锁给解了。

常见的,分布式锁有三种实现方式:


第一:数据库乐观锁;


利用表的唯一索引行级锁进行加解锁,加锁:

加锁:insert into methodLock(method_name,desc) values (‘method_name’,‘desc’)


解锁:delete from methodLock where method_name ='method_nam


第二:基于Redis的分布式锁;


jedis.setnx(String key, String value, String nxxx, String expx, int time)


第三:基于ZooKeeper的分布式锁


zk 是一种提供配置管理、分布式协同以及命名的中心化服务,用于集群配置中心管理,服务的注册监听等。zookeeper 分布式锁的实现利用zookeeper 管理配置中心的watcher机制(观察者模式),对竞争分布式锁的客户端维护了一张临时顺序表。表中每个节点代表一个客户端。

v2-e904e6e884f9fb6b1db1969e70a83d2c_1440w.jpg

相关文章
|
2月前
|
监控 Java API
Spring Boot 3.2 结合 Spring Cloud 微服务架构实操指南 现代分布式应用系统构建实战教程
Spring Boot 3.2 + Spring Cloud 2023.0 微服务架构实践摘要 本文基于Spring Boot 3.2.5和Spring Cloud 2023.0.1最新稳定版本,演示现代微服务架构的构建过程。主要内容包括: 技术栈选择:采用Spring Cloud Netflix Eureka 4.1.0作为服务注册中心,Resilience4j 2.1.0替代Hystrix实现熔断机制,配合OpenFeign和Gateway等组件。 核心实操步骤: 搭建Eureka注册中心服务 构建商品
521 3
|
3月前
|
人工智能 Kubernetes 数据可视化
Kubernetes下的分布式采集系统设计与实战:趋势监测失效引发的架构进化
本文回顾了一次关键词监测任务在容器集群中失效的全过程,分析了中转IP复用、调度节奏和异常处理等隐性风险,并提出通过解耦架构、动态IP分发和行为模拟优化采集策略,最终实现稳定高效的数据抓取与分析。
Kubernetes下的分布式采集系统设计与实战:趋势监测失效引发的架构进化
|
13天前
|
缓存 Cloud Native 中间件
《聊聊分布式》从单体到分布式:电商系统架构演进之路
本文系统阐述了电商平台从单体到分布式架构的演进历程,剖析了单体架构的局限性与分布式架构的优势,结合淘宝、京东等真实案例,深入探讨了服务拆分、数据库分片、中间件体系等关键技术实践,并总结了渐进式迁移策略与核心经验,为大型应用架构升级提供了全面参考。
|
29天前
|
存储 NoSQL 前端开发
【赵渝强老师】MongoDB的分布式存储架构
MongoDB分片通过将数据分布到多台服务器,实现海量数据的高效存储与读写。其架构包含路由、配置服务器和分片服务器,支持水平扩展,结合复制集保障高可用性,适用于大规模生产环境。
178 1
|
1月前
|
消息中间件 缓存 监控
中间件架构设计与实践:构建高性能分布式系统的核心基石
摘要 本文系统探讨了中间件技术及其在分布式系统中的核心价值。作者首先定义了中间件作为连接系统组件的"神经网络",强调其在数据传输、系统稳定性和扩展性中的关键作用。随后详细分类了中间件体系,包括通信中间件(如RabbitMQ/Kafka)、数据中间件(如Redis/MyCAT)等类型。文章重点剖析了消息中间件的实现机制,通过Spring Boot代码示例展示了消息生产者的完整实现,涵盖消息ID生成、持久化、批量发送及重试机制等关键技术点。最后,作者指出中间件架构设计对系统性能的决定性影响,
|
6月前
|
人工智能 安全 Java
智慧工地源码,Java语言开发,微服务架构,支持分布式和集群部署,多端覆盖
智慧工地是“互联网+建筑工地”的创新模式,基于物联网、移动互联网、BIM、大数据、人工智能等技术,实现对施工现场人员、设备、材料、安全等环节的智能化管理。其解决方案涵盖数据大屏、移动APP和PC管理端,采用高性能Java微服务架构,支持分布式与集群部署,结合Redis、消息队列等技术确保系统稳定高效。通过大数据驱动决策、物联网实时监测预警及AI智能视频监控,消除数据孤岛,提升项目可控性与安全性。智慧工地提供专家级远程管理服务,助力施工质量和安全管理升级,同时依托可扩展平台、多端应用和丰富设备接口,满足多样化需求,推动建筑行业数字化转型。
242 5
|
4月前
|
监控 算法 关系型数据库
分布式事务难题终结:Seata+DRDS全局事务一致性架构设计
在分布式系统中,CAP定理限制了可用性、一致性与分区容错的三者兼得,尤其在网络分区时需做出取舍。为应对这一挑战,最终一致性方案成为常见选择。以电商订单系统为例,微服务化后,原本的本地事务演变为跨数据库的分布式事务,暴露出全局锁失效、事务边界模糊及协议差异等问题。本文深入探讨了基于 Seata 与 DRDS 的分布式事务解决方案,涵盖 AT 模式实践、分片策略优化、典型问题处理、性能调优及高级特性实现,结合实际业务场景提供可落地的技术路径与架构设计原则。通过压测验证,该方案在事务延迟、TPS 及失败率等方面均取得显著优化效果。
295 61
|
5月前
|
监控 Linux 应用服务中间件
Linux多节点多硬盘部署MinIO:分布式MinIO集群部署指南搭建高可用架构实践
通过以上步骤,已成功基于已有的 MinIO 服务,扩展为一个 MinIO 集群。该集群具有高可用性和容错性,适合生产环境使用。如果有任何问题,请检查日志或参考MinIO 官方文档。作者联系方式vx:2743642415。
1829 57
|
9月前
|
存储 缓存 NoSQL
分布式系统架构8:分布式缓存
本文介绍了分布式缓存的理论知识及Redis集群的应用,探讨了AP与CP的区别,Redis作为AP系统具备高性能和高可用性但不保证强一致性。文章还讲解了透明多级缓存(TMC)的概念及其优缺点,并详细分析了memcached和Redis的分布式实现方案。此外,针对缓存穿透、击穿、雪崩和污染等常见问题提供了应对策略,强调了Cache Aside模式在解决数据一致性方面的作用。最后指出,面试中关于缓存的问题多围绕Redis展开,建议深入学习相关知识点。
646 8
|
5月前
|
消息中间件 缓存 算法
分布式开发:数字时代的高性能架构革命-为什么要用分布式?优雅草卓伊凡
分布式开发:数字时代的高性能架构革命-为什么要用分布式?优雅草卓伊凡
298 0
分布式开发:数字时代的高性能架构革命-为什么要用分布式?优雅草卓伊凡
下一篇
开通oss服务