分布式系统架构3:服务容错

简介: 分布式系统因其复杂性,故障几乎是必然的。那么如何让系统在不可避免的故障中依然保持稳定?本文详细介绍了分布式架构中7种核心的服务容错策略,包括故障转移、快速失败、安全失败等,以及它们在实际业务场景中的应用。无论是支付场景的快速失败,还是日志采集的安全失败,每种策略都有自己的适用领域和优缺点。此外,文章还为技术面试提供了解题思路,助你在关键时刻脱颖而出。掌握这些策略,不仅能提升系统健壮性,还能让你的技术栈更上一层楼!快来深入学习,走向架构师之路吧!

这是小卷对分布式系统架构学习的第3篇文章,虽然知道大家都不喜欢看纯技术文章,写了也没多少阅读量,但是个人要成长的话,还是需要往深一点的技术上去探索的

1.为什么需要容错

分布式系统的本质是不可靠的,一个大的服务集群中,程序可能崩溃、节点可能宕机、网络可能中断,这些“意外情况”其实全部都在“意料之中”。故障的发生是必然的,所以需要设计一套健壮的容错机制来应对这些问题。

容错策略,指的是“面对故障,我们该做些什么”;而容错设计模式,指的是“要实现某种容错策略,我们该如何去做”。下面介绍7种常见的容错策略。

2.七种容错策略

7种常见的容错策略:故障转移、快速失败、安全失败、沉默失败、故障恢复、并行调用和广播调用

故障转移Failover

概念:分布式服务中,服务会有多个副本。如果调用的服务器出现故障,系统不会直接返回失败,而是切换到其他服务副本上,保证返回调用成功的结果。

故障转移需要设置重试次数,并且需根据实际业务场景考虑是否设置故障转移。示例:

现在有Service A → Service B → Service C 这么一条调用链。假设 A 的超时阈值为 100ms,而 B 调用 C 需要 60ms,然后不幸失败了,这时候做故障转移其实已经没有太大意义了。因为即使B调用C故障转移成功了,调用耗时至少增加60ms,A已经超时了,这种故障转移对系统无利。

适用场景:读多写少的采集,如:电商商品查询;对成功率要求高的采集

快速失败Failfast

当业务场景不允许,或者服务是非幂等时,重复调用会产生脏数据,就不能用故障转移了,需要用到快速失败。

概念:服务在调用失败后,立即返回错误,不做任何重试

示例:支付场景中,调用银行扣款接口,返回结果是网络异常。这时候无法区分是否已扣款了,为避免重复扣款,只能服务抛出异常报错,不能重试

适用场景:高实时性场景、交易支付场景

缺点:调用方需有较高容错能力

安全失败Failsafe

服务也区分主路和旁路,旁路的特点是服务失败了也不影响核心业务。比如spring项目中的日志、Debug信息等。旁路逻辑不影响最终结果。因此,对这类逻辑的容错策略就是,即使旁路逻辑失败了,也当做正确返回。

概念:当服务调用失败时,忽略异常并返回一个默认的结果,确保系统继续运行。

适用场景:非核心业务场景,日志处理、监控采集

优点:最大化保证系统稳定性

示例:java中的try-catch,Dubbo中的failsafe策略

沉默失败Failsilent

概念:大量请求如果都等到超时才失败,可能将系统的线程、内存、网络资源耗尽,影响整个服务稳定性。对该场景的失败策略是:当请求失败后,默认服务提供者一定时间内无法提供服务了,不再向它分配流量,将错误隔离开来。

实际应用场景:分布式系统中,单点故障时,流量调度系统不再给该节点分配流量,每隔5分钟自动检查节点是否恢复。

故障恢复Failback

不是单独存在的,通常默认使用快速失败+故障恢复策略

概念:故障恢复是指在服务调用失败后,将失败的请求异步存储下来,存到数据库或消息队列中,并定时重试或补偿,直到调用成功。这种方式对业务具有一定的“追溯”能力。故障恢复也需有最大重试次数限制

适用场景:实时性要求不高,数据一致性要求高的场景。如:库存更新、订单状态同步

优点:提高系统最终一致性

缺点:系统需配合消息队列,实现复杂

小结:前面5种容错策略都是针对调用失败后如何进行弥补的,下面2种是调用之前如何提供成功率的

并行调用Forking

概念:同时调用多个服务节点,只要任意一个节点返回成功结果即认为调用成功。对于调用结果相同或相似的服务节点,这种方式可大幅提高调用成功率。

适用场景:多副本部署场景、调用耗时长且高可用要求的场景。如:数据库分片存储查询

优点:提供成功率,减少等待时间(取决于最先返回成功的节点)

缺点:增加系统开销

广播调用Broadcast

概念:请求发送给所有服务实例,并收集所有返回结果,要求所有请求全部成功才算成功。这种方式适用于需要对多个节点进行同步操作的场景

适用场景:刷新分布式缓存、配置同步

优点:所有节点都能执行操作

缺点:并行执行开销大

实现方式:Dubbo的broadcast策略支持广播调用

7种容错策略对比

容错策略 优点 缺点 应用场景
故障转移 系统自动处理,调用者对失败信息不可见 会增加调用时间,也会导致额外的资源开销 调用幂等服务,对调用时间不敏感的场景
快速失败 调用者有失败的处理完全控制,不依赖服务的幂等性 调用者必须正确处理失败逻辑,容易引起雪崩 调用非幂等的服务,超时阈值较低的场景
安全失败 不影响主逻辑 只适用于旁路调用 调用链中的旁路服务
沉默失败 控制错误不影响全局 出错的地方将有一段时间内不可用 频繁超时的服务
故障恢复 调用失败后自动重试,也不影响主逻辑 推荐用于旁路服务调用,重试任务可能堆积,重试仍然可能失败 调用链中的旁路服务,对实时性要求不高的主逻辑
并行调用 尽可能在最短时间内获得最高的成功率 额外消耗机器资源,大部分调用可能是无用功 资源充足且失效容忍度低的场景
广播调用 支持同时对批量的服务提供者发起调用 资源消耗大,失败概率高 只适用于批量操作的场景

面试题准备

如果一个业务系统需要调用第三方的5个接口,这5个接口中只要有3个接口返回成功了就认为成功,问如何设计并实现

周志明大佬的答复:

我看这题是个圈套呀,大多数的架构设计题目,固定答案往往都是不对的。因为做技术设计是为了解决实际问题,不能谈兵,所以方案要根据希望实现的目标而定:

如果目的是这项业务尽可能快速地完成,那就forking策略,5个一起调用,成功3个算过。

如果目的是这项业务尽可能少消耗资源,那就failfast策略,先对它们出错概率做个先验判断,排序后先调用最容易出错的,错够3次算失败,后面的不执行。

如果目的是这项业务尽可能高概率地完成,那就failover策略

相关文章
|
14天前
|
存储 Prometheus Cloud Native
分布式系统架构6:链路追踪
本文深入探讨了分布式系统中的链路追踪理论,涵盖追踪与跨度的概念、追踪系统的模块划分及数据收集的三种方式。链路追踪旨在解决复杂分布式系统中请求流转路径不清晰的问题,帮助快速定位故障和性能瓶颈。文中介绍了基于日志、服务探针和边车代理的数据收集方法,并简述了OpenTracing、OpenCensus和OpenTelemetry等链路追踪协议的发展历程及其特点。通过理解这些概念,可以更好地掌握开源链路追踪框架的使用。
69 41
|
1天前
|
存储 关系型数据库 分布式数据库
[PolarDB实操课] 01.PolarDB分布式版架构介绍
《PolarDB实操课》之“PolarDB分布式版架构介绍”由阿里云架构师王江颖主讲。课程涵盖PolarDB-X的分布式架构、典型业务场景(如实时交易、海量数据存储等)、分布式焦点问题(如业务连续性、一致性保障等)及技术架构详解。PolarDB-X基于Share-Nothing架构,支持HTAP能力,具备高可用性和容错性,适用于多种分布式改造和迁移场景。课程链接:[https://developer.aliyun.com/live/253957](https://developer.aliyun.com/live/253957)。更多内容可访问阿里云培训中心。
[PolarDB实操课] 01.PolarDB分布式版架构介绍
|
25天前
|
设计模式 存储 算法
分布式系统架构5:限流设计模式
本文是小卷关于分布式系统架构学习的第5篇,重点介绍限流器及4种常见的限流设计模式:流量计数器、滑动窗口、漏桶和令牌桶。限流旨在保护系统免受超额流量冲击,确保资源合理分配。流量计数器简单但存在边界问题;滑动窗口更精细地控制流量;漏桶平滑流量但配置复杂;令牌桶允许突发流量。此外,还简要介绍了分布式限流的概念及实现方式,强调了限流的代价与收益权衡。
70 11
|
27天前
|
设计模式 监控 Java
分布式系统架构4:容错设计模式
这是小卷对分布式系统架构学习的第4篇文章,重点介绍了三种常见的容错设计模式:断路器模式、舱壁隔离模式和重试模式。断路器模式防止服务故障蔓延,舱壁隔离模式通过资源隔离避免全局影响,重试模式提升短期故障下的调用成功率。文章还对比了这些模式的优缺点及适用场景,并解释了服务熔断与服务降级的区别。尽管技术文章阅读量不高,但小卷坚持每日更新以促进个人成长。
50 11
|
3月前
|
NoSQL Java Redis
太惨痛: Redis 分布式锁 5个大坑,又大又深, 如何才能 避开 ?
Redis分布式锁在高并发场景下是重要的技术手段,但其实现过程中常遇到五大深坑:**原子性问题**、**连接耗尽问题**、**锁过期问题**、**锁失效问题**以及**锁分段问题**。这些问题不仅影响系统的稳定性和性能,还可能导致数据不一致。尼恩在实际项目中总结了这些坑,并提供了详细的解决方案,包括使用Lua脚本保证原子性、设置合理的锁过期时间和使用看门狗机制、以及通过锁分段提升性能。这些经验和技巧对面试和实际开发都有很大帮助,值得深入学习和实践。
太惨痛: Redis 分布式锁 5个大坑,又大又深, 如何才能 避开 ?
|
5月前
|
NoSQL Redis
基于Redis的高可用分布式锁——RedLock
这篇文章介绍了基于Redis的高可用分布式锁RedLock的概念、工作流程、获取和释放锁的方法,以及RedLock相比单机锁在高可用性上的优势,同时指出了其在某些特殊场景下的不足,并提到了ZooKeeper作为另一种实现分布式锁的方案。
148 2
基于Redis的高可用分布式锁——RedLock
|
1月前
|
存储 NoSQL Java
使用lock4j-redis-template-spring-boot-starter实现redis分布式锁
通过使用 `lock4j-redis-template-spring-boot-starter`,我们可以轻松实现 Redis 分布式锁,从而解决分布式系统中多个实例并发访问共享资源的问题。合理配置和使用分布式锁,可以有效提高系统的稳定性和数据的一致性。希望本文对你在实际项目中使用 Redis 分布式锁有所帮助。
146 5
|
2月前
|
NoSQL Java 数据处理
基于Redis海量数据场景分布式ID架构实践
【11月更文挑战第30天】在现代分布式系统中,生成全局唯一的ID是一个常见且重要的需求。在微服务架构中,各个服务可能需要生成唯一标识符,如用户ID、订单ID等。传统的自增ID已经无法满足在集群环境下保持唯一性的要求,而分布式ID解决方案能够确保即使在多个实例间也能生成全局唯一的标识符。本文将深入探讨如何利用Redis实现分布式ID生成,并通过Java语言展示多个示例,同时分析每个实践方案的优缺点。
81 8
|
2月前
|
NoSQL Redis
Redis分布式锁如何实现 ?
Redis分布式锁通过SETNX指令实现,确保仅在键不存在时设置值。此机制用于控制多个线程对共享资源的访问,避免并发冲突。然而,实际应用中需解决死锁、锁超时、归一化、可重入及阻塞等问题,以确保系统的稳定性和可靠性。解决方案包括设置锁超时、引入Watch Dog机制、使用ThreadLocal绑定加解锁操作、实现计数器支持可重入锁以及采用自旋锁思想处理阻塞请求。
64 16
|
2月前
|
缓存 NoSQL PHP
Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出
本文深入探讨了Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出。文章还介绍了Redis在页面缓存、数据缓存和会话缓存等应用场景中的使用,并强调了缓存数据一致性、过期时间设置、容量控制和安全问题的重要性。
52 5

热门文章

最新文章