算法基础——容错
容错机制
常见的容错机制可以分为以下6种:
- FailOver
- FailFast
- FailSafe
- FailBack
- Forking
- BroadCast
前4种容错机制针对的是服务调用失败的场景,而后面2种容错机制更多的是对数据实时性和数据可靠性方面的考虑和容错的实现。
FailOver失败自动切换
失败自动切换机制是指当调用该服务集群的某个节点失败时,自动切换到该服务集群的另外一个节点并进行重试,其中切换机制类似于负载均衡机制,不过一般采用轮询方式。这种容错机制通常适用于读操作,所以可以请求从该服务集群的多个节点的任意一个节点获取数据。由于需要切换到服务集群的另外一个节点进行服务重试,因此整个请求处理流程的时间延迟会加大。
FailFast快速失败
快速失败机制是指当服务调用失败时,直接返回错误,而不会进行重试或者切换到服务集群的另外一个节点进行调用,即要么成功,要么失败,只发起一次服务调用请求。这种机制通常适用于非幂等的操作,因为服务调用失败的原因包括服务节点机器宕机导致服务不可用;服务可用,但是两个服务节点之间的网络出现延迟或者被调用的服务节点繁忙,处理请求缓慢,导致返回结果超时。所以当服务调用失败时,可能确实没有进行操作,也可能进行了操作,但是返回响应结果超时或者丢失,而该操作是非幂等的,故不能进行重复操作,否则会导致数据不一致。
FailSafe失败安全
失败安全机制与快速失败机制类似,都是只发起一次服务调用,要么成功,要么失败,不会进行重试操作。不过与快速失败不同的是,失败安全机制在调用失败时会进行日志记录。所以可以通过对日志进行监控和分析来及时了解服务调用情况,及早发现和处理服务调用失败的情况,以及对于重要服务的调用可以通过日志的数据来进行补偿恢复。
FailBack失败自动恢复
失败自动恢复机制与失败安全机制类似,在服务调用失败时也会进行服务调用的记录,不过在记录的基础上,增加了自动定时重发的逻辑,适用于异步、幂等性的请求调用或者消息系统中允许消息重复的场景。
Forking并行
并行机制通常用于实时性要求较高的读操作的场景,其基本工作过程为并行调用服务集群的所有节点,由于是读操作,所有服务节点返回的数据都是相同的,因此只要有一个服务节点返回调用成功则返回响应给客户端。这种机制相对于失败自动切换机制,由于是对所有服务节点发起并行调用,而不是在调用失败时才一个个轮询切换直到调用成功,因此延迟较小,实时性较高,但机器的系统资源开销较大,所以如果需要进行这种调用,则需要保证机器性能较高。
BroadCast广播调用
广播调用机制与并行调用机制类似,也需要对服务集群的每个节点都发起一次调用,不过不同的是,广播调用通常用于服务集群的每个节点都维护了本地状态,然后需要对这种本地状态进行写操作的场景,即需要同步写操作给服务集群的每个节点,从而保证每个节点的数据一致性和可靠性。
总结
容错机制 | 设计目标 | 实现原理 | 优点 | 缺点 |
---|---|---|---|---|
FailOver | 确保服务的连续性和可用性 | 当主系统发生故障时,备用系统立即接管任务 | 高可用性,服务不中断 | 资源消耗大,切换时间可能导致延迟增加 |
FailFast | 快速发现并报告错误,避免错误传播 | 系统检测到错误时立即停止操作并报告错误 | 快速定位问题,防止错误扩散 | 用户体验差,可能导致系统中断 |
FailSafe | 确保系统在故障情况下仍能稳定运行 | 通过冗余设计、隔离错误、优雅降级等策略 | 系统稳定性强,用户体验良好 | 难以及时发现潜在问题,可能掩盖错误 |
FailBack | 在故障恢复后自动将服务切换回主系统 | 故障恢复后,系统自动将服务从备用切换回主 | 充分利用主组件性能,减少备用资源占用 | 可能再次引入短暂停机时间,需确保数据一致性 |
Forking | 提高系统的并发处理能力和容错能力 | 并行调用多个服务,只要一个成功即返回成功 | 提高系统并发处理能力,容错能力强 | 浪费服务资源,可能增加系统复杂性 |
Broadcast | 确保所有服务节点都接收到请求 | 广播调用所有服务,逐个调用 | 确保所有节点接收到请求,适用于配置更新 | 速度慢,任意一个服务出错导致整个调用失败 |
拓展——数据库系统容错机制
数据库领域也有一些经典容错机制,如“一主多备”“两地三中心”等,这些都是数据库集群系统的高可用性的解决方案:
一主多备
概念:一主多备指一个主数据库负责处理日常的读写操作,而多个备用数据库实时同步主数据库的数据。当主数据库出现故障时,备用数据库可以迅速接管其工作,保证业务的连续性。
备数据中心一般有热备、冷备、双活3种备份方式。
设计目标:提高数据库系统的可用性和可靠性,确保在主数据库发生故障时,系统能够快速切换到备用数据库,减少服务中断时间。
实现原理:主数据库在处理事务时,会将事务日志实时发送给备用数据库,备用数据库通过应用这些日志来保持与主数据库的数据一致性。在主数据库故障时,通过切换机制,将备用数据库提升为主数据库,继续提供服务。
优缺点:
-
优点:实现简单,成本较低,能够有效提高系统的可用性。
-
缺点:主数据库的压力较大,且在主数据库故障时,切换过程可能会有短暂的服务中断。
两地三中心
概念:“两地三中心”是一种高可用性和灾难恢复能力兼具的数据库部署架构。其中,“两地”指本地和异地两个不同的地理位置,“三中心”则包括本地数据中心、本地备份数据中心和异地数据备份中心。
在热备的情况下,只有主数据中心承担用户的业务,此时备数据中心对主数据中心进行实时的备份,当主数据中心“挂掉”以后,备数据中心可以自动接管主数据中心的业务,用户的业务不会中断,所以感觉不到数据中心的切换。在冷备的情况下,也是只有主数据中心承担业务,但是备数据中心不会对主数据中心进行实时备份,可能周期性地进行备份或者干脆不进行备份,如果主数据中心挂掉了,用户的业务就会中断。而采用双活是考虑到备数据中心只用于备份太浪费资源了,所以让主备两个数据中心都同时承担用户的业务,此时,主备两个数据中心互为备份,并且进行实时备份。一般来说,主数据中心的负载可能会多一些,如分担60%~70%的业务,备数据中心只分担30%~40%的业务。
设计目标:满足金融等行业对数据安全性和业务连续性的严格要求,能够在同城或异地发生灾难时,快速恢复业务,保证数据的完整性和一致性。
实现原理:生产中心负责日常的业务处理,同城容灾中心通过高速链路与生产中心实时同步数据,并具备独立承担业务运行的能力。异地容灾中心则用于备份数据,当同城的两个中心都发生故障时,可以利用异地容灾中心的数据进行业务恢复。
优缺点:
-
优点:提供了极高的可用性和灾难恢复能力,能够有效应对各种规模的灾难事件。
-
缺点:部署和维护成本较高,需要考虑数据同步的延迟和一致性问题。
容错算法
以下是经典的容错算法:
CRC(Cyclic Redundancy Check,循环冗余校验)
概念:CRC是一种在数据通信和存储领域广泛应用的错误检测码技术。通过在数据中添加一段校验位(即CRC码),接收方可以检验这些校验位以确定数据是否在传输过程中遭到损坏或篡改。
它主要是用来检测数据传输或存储中的错误,比如发送数据时附加校验码,接收端再用同样的算法验证。通常应用于数据传输和存储领域,如网络通信、文件传输等,确保数据的完整性和正确性。
实现原理:将数据视为一个大整数,通过一个预定的生成多项式对数据进行模2除法,得到的余数作为校验码附加到数据后面。接收端使用相同的生成多项式对数据进行校验,如果余数为0,则表示数据在传输过程中未被破坏。
优点:
-
高检测能力:能够检测到比其生成多项式长度更短的错误模式,对于更长的消息,几乎可以检测出所有的错误模式。
-
易于硬件实现:算法相对简单,易于硬件实现。
缺点:
-
性能瓶颈:随着数据传输速率的提升以及数据量的增大,传统的CRC算法可能无法满足实时性要求。
-
误判风险:虽然误判率低,但在某些情况下仍可能出现误判。
ARQ(Automatic Repeat reQuest,自动重传请求)
概念:ARQ是一种用于数据传输的容错机制,当发送方发送数据后,会等待接收方的确认信息,如果在规定时间内未收到确认信息,则会自动重传数据。
这算法和CRC有点不一样,它是通过确认和重传来保证数据传输的可靠性。
其主要有三种类型:停止等待、连续ARQ和选择性重传。
停止等待ARQ(Stop-and-Wait ARQ)
实现原理:
-
发送方:发送方每发送一个数据帧后,必须等待接收方的确认(ACK)或否认(NAK)。
-
接收方:接收方收到数据帧后,进行校验。如果校验通过,则发送ACK;如果校验失败,则发送NAK。
-
重传机制:发送方收到ACK后,可以发送下一个数据帧;如果收到NAK或超时未收到ACK,则重传该数据帧。
连续ARQ(Continuous ARQ)
实现原理:
-
发送方:发送方可以连续发送多个数据帧,而不需要等待每个数据帧的确认。
-
接收方:接收方可以连续接收数据帧,并对每个数据帧进行校验。如果校验通过,则接收该数据帧;如果校验失败,则丢弃该数据帧,并发送否认(NAK)。
-
重传机制:发送方在发送一定数量的数据帧后,等待接收方的确认。如果收到NAK或超时未收到ACK,则重传从出错的数据帧开始的所有数据帧。
选择性重传ARQ(Selective Repeat ARQ)
实现原理:
-
发送方:发送方可以连续发送多个数据帧,而不需要等待每个数据帧的确认。
-
接收方:接收方可以连续接收数据帧,并对每个数据帧进行校验。如果校验通过,则接收该数据帧;如果校验失败,则丢弃该数据帧,并发送否认(NAK)。
-
重传机制:发送方在发送一定数量的数据帧后,等待接收方的确认。如果收到NAK或超时未收到ACK,则只重传出错的数据帧,而不是从出错的数据帧开始的所有后续数据帧。
特性 | 停止等待ARQ | 连续ARQ | 选择性重传ARQ |
---|---|---|---|
传输效率 | 低,每次只能发送一个数据帧 | 高,可以连续发送多个数据帧 | 高,可以连续发送多个数据帧 |
延迟 | 高,需要等待确认 | 低,减少了等待确认的时间 | 低,减少了等待确认的时间 |
重传效率 | 低,每次重传一个数据帧 | 低,需要重传从出错的数据帧开始的所有数据帧 | 高,只重传出错的数据帧 |
复杂性 | 低,机制简单 | 高,需要管理多个数据帧的发送和确认 | 高,需要管理多个数据帧的发送和确认 |
应用场景 | 简单网络通信、教学和实验 | 数据传输、网络通信 | 数据传输、网络通信 |
ARQ机制广泛应用于互联网中的数据传输,确保数据包能够可靠地从发送方传输到接收方。例如,在TCP/IP协议中,ARQ机制被用来保证数据的可靠传输。
在文件传输过程中,ARQ机制可以确保文件的完整性和正确性。例如,当通过网络传输大型文件时,ARQ机制可以检测并纠正传输过程中出现的错误,确保文件能够完整无误地到达接收方。
优点:
-
可靠性高:通过重传机制,确保数据能够可靠地到达接收方。
-
简单易实现:实现相对简单,易于在各种通信协议中应用。
缺点:
-
延迟增加:重传机制可能导致数据传输的延迟增加。
-
资源消耗:频繁的重传可能增加网络资源的消耗。
DHT(Distributed Hash Table,分布式哈希表)
概念:DHT是一种在分布式系统中用于存储和检索数据的算法。通过将数据分布式存储在多个节点上,实现数据的高效存储和检索。
DHT算法比较复杂,涉及到分布式系统中的数据存储和检索。常用于分布式系统和P2P网络中,如BitTorrent等,实现数据的高效共享和分发。
实现原理:使用哈希函数将数据映射到特定的节点上,每个节点只存储一部分数据。当需要检索数据时,通过哈希函数计算出数据所在的节点,然后从该节点获取数据。
优点:
-
高容错性:数据分布式存储在多个节点上,即使部分节点故障,数据仍然可以被访问。
-
可扩展性好:系统可以动态添加或删除节点,而不会影响整体功能。
缺点:
-
一致性问题:在数据更新时,可能需要处理一致性问题,确保所有节点的数据一致。
-
网络延迟:数据存储和检索可能涉及多个节点,导致网络延迟增加。
Checkpoint(检查点)
概念:Checkpoint是数据库系统中的一种机制,用于周期性地将系统状态保存到磁盘上,以便在发生故障时能够快速恢复。
Checkpoint算法是数据库系统中的一个关键机制,通过定期保存数据状态,当系统发生故障时,可以从最近的检查点恢复。广泛应用于各种数据库系统中,用于提高系统的可靠性和恢复能力。
实现原理:数据库系统会周期性地执行Checkpoint操作,将内存中的数据和日志记录应用到磁盘上的数据库文件中。这样,在系统发生故障时,可以从最近的检查点开始恢复,减少恢复时间。
优点:
-
减少恢复时间:通过定期保存系统状态,减少系统恢复时需要处理的日志量,从而缩短恢复时间。
-
提高系统可靠性:确保在发生故障时,系统能够快速恢复到一致的状态。
缺点:
-
资源消耗:Checkpoint操作需要占用一定的磁盘和内存资源。
-
复杂性增加:需要管理检查点的生成、保存和恢复过程,增加了系统的复杂性。
No Order Write(无序写)
概念:No Order Write是一种内存管理策略,允许内存中的写入操作发生在任意顺序,以减少故障发生的可能性。
No Order Write算法是内存管理中的一个策略,适用于需要高并发写入的系统,如高性能数据库系统、实时数据处理系统等,提高系统的写入性能和容错能力。
实现原理:当应用程序请求写入某一页时,将请求放入一个队列中,当内存中的某一页已经空闲时,从队列中取出一个请求,并执行写入操作。
优点:
-
提高性能:通过允许写入操作的无序执行,提高了内存的利用率和写入性能。
-
减少冲突:减少了写入操作之间的冲突,提高了系统的并发性能。
缺点:
-
数据一致性问题:需要确保写入操作的顺序不会影响数据的一致性。
-
实现复杂性:需要管理写入请求的队列和执行顺序,增加了系统的复杂性。
WAL(Write-Ahead Logging,预写日志)
概念:WAL是一种在数据写入磁盘之前,先将修改的数据记录到日志文件中的技术。这种技术确保了在系统崩溃或断电等情况下,可以通过日志文件恢复数据,保证数据的一致性和持久性。
WAL算法是数据库系统中的一个关键机制,广泛应用于各种数据库系统,用于保证数据的持久性和一致性。
实现原理:当对数据库中的数据进行修改时,系统会先将修改操作记录到日志缓冲区,然后在适当的时机将日志缓冲区中的内容写入磁盘上的日志文件。在数据真正写入磁盘之前,日志文件已经记录了所有的修改操作。
优点:
-
数据一致性:确保在系统崩溃后,数据可以恢复到一致的状态。
-
性能提升:通过减少直接对数据文件的随机写入,提高数据库的写入性能。
缺点:
-
日志管理复杂:需要管理日志文件的生成、归档和清理,增加了系统的复杂性。
-
磁盘空间占用:日志文件会占用一定的磁盘空间,需要定期清理或归档。
WBL(Write-Behind Logging,写后日志)
设计WBL的核心原则在于,记录数据库中的数据改变了什么,而不是记录其是如何改变的。WBL在数据库将数据的更改全部持久化后,才将日志写入NVM设备,并且通过原子写入日志的模式,保证了事务修改数据的持久性和原子性。
WBL还减少了每条事务需要记录的日志的大小,因此大大减少了对NVM设备的写入次数,增加了NVM设备的使用寿命。
概念:WBL是一种在数据写入内存后,再将修改的数据记录到日志文件中的技术。这种技术可以提高系统的写入性能,但可能会增加数据丢失的风险。
WBL算法和WAL有点类似,但它是异步记录日志。在某些对性能要求较高的场景中使用,如Redis的AOF(Append Only File)持久化机制,通过写后日志来提高性能。
实现原理:当对数据库中的数据进行修改时,系统会先将修改操作应用到内存中的数据结构,然后在适当的时机将修改操作记录到日志文件中。这样,数据的修改操作可以快速完成,而日志记录则可以在后台异步进行。
优点:
-
高性能:通过异步记录日志,减少了对数据文件的直接写入,提高了系统的写入性能。
-
简单实现:不需要在写入数据之前进行日志记录,简化了日志管理。
缺点:
-
数据丢失风险:如果系统在日志记录完成之前发生故障,可能会导致部分数据丢失。
-
日志恢复复杂:在系统恢复时,需要重放日志文件中的记录,增加了恢复的复杂性。
总结
其实前面提到的一致性算法,本质也是容错的一部分。容错是涉及内容很多的领域,也是一个非常关键的技术,因为如果不能保证数据的正确性,就丧失了最基本的保证。本文提到的容错算法更多的是偏向大数据中数据系统的容错保障,虽然现在关于容错有各种各样的设计和应用,但深入其本质上都是一个取舍的问题,就是性能和容错之间的取舍。
在实际落地时,我们需要依据自身的业务特性来选定合适的容错机制,针对服务调用失败的情况采取合适的处理方式,才能在保障容错的前提下,尽可能提到性能。