集群容错机制:failover、failfast、failback、failsafe、forking
1.failover:失效转移
失效转移(failover)是一种备份操作模式,当主要组件由于失效或预定关机时间的原因而无法工作时,这种模式中的系统组件(比如处理机、服务器、网络或数据库)的功能被转嫁到二级系统组件。对于希望使系统具有更高的故障容忍力,失效转移是一定会被经常使用的紧急任务系统的主要部分。这个程序包括自动卸下任务交给备用系统组件,这样程序对于终端用户能够尽可能的无故障。失效转移能应用于系统的许多方面:举个例子,在个人电脑内部,失效转移也许是保护故障的处理机的一种机制;在网络内部,失效转移能够应用于许多网络组件或系统组件,比如连接通路、存储设备或者环球网服务器。
最初,存储数据在非常基本的配置下被连接到服务器:点对点或者交叉连接。在这种环境下,单一服务器的故障常常使得大量的用户无法访问数据,直到那个服务器重新在线服务。近来有更多的发展,比如存储区域网络(SAN),在服务器和数据存储系统之中建立许多到许多的连通性。通常,存储网络在服务器和系统之间使用许多通路(每个通路由包括所有有关组件的完全的配置组成)。一个失效的通路可能是由于通路上一些单独组件的故障。多重连接通路(每个通路都有多余组件)常常帮助确保线路在一个(或多个)通路失效情况下仍然可行。自动失效转移(failover)的能力在于尽管由于设备问题导致必然的故障然而正常功能仍能被维持。
其要点在于有主有备,且主故障时备可启用,并设置为主。如Mysql的双Master模式,当正在使用的Master出现故障时,可以拿备Master做主使用。
2.failfast:快速失败
从字面含义看就是“快速失败”,尽可能的发现系统中的错误,使系统能够按照事先设定好的错误的流程执行,对应的方式是“fault-tolerant(错误容忍)”。以JAVA集合(Collection)的快速失败为例,当多个线程对同一个集合的内容进行操作时,就可能会产生fail-fast事件。例如:当某一个线程A通过iterator去遍历某集合的过程中,若该集合的内容被其他线程所改变了;那么线程A访问集合时,就会抛出ConcurrentModificationException异常(发现错误执行设定好的错误的流程),产生fail-fast事件。
要了解fail-fast机制,我们首先要对ConcurrentModificationException 异常有所了解。当方法检测到对象的并发修改,但不允许这种修改时就抛出该异常。同时需要注意的是,该异常不会始终指出对象已经由不同线程并发修改,如果单线程违反了规则,同样也有可能会抛出该异常。
诚然,迭代器的快速失败行为无法得到保证,它不能保证一定会出现该错误,但是快速失败操作会尽最大努力抛出ConcurrentModificationException异常,所以因此,为提高此类操作的正确性而编写一个依赖于此异常的程序是错误的做法,正确做法是:ConcurrentModificationException 应该仅用于检测 bug。
3.failback:失效自动恢复
Fail-over之后的自动恢复,在簇网络系统(有两台或多台服务器互联的网络)中,由于要某台服务器进行维修,需要网络资源和服务暂时重定向到备用系统。在此之后将网络资源和服务器恢复为由原始主机提供的过程,称为自动恢复
4.failsafe:失效安全
Fail-Safe的含义为“失效安全”,即使在故障的情况下也不会造成伤害或者尽量减少伤害。维基百科上一个形象的例子是红绿灯的“冲突监测模块”当监测到错误或者冲突的信号时会将十字路口的红绿灯变为闪烁错误模式,而不是全部显示为绿灯。
在Java中,Failsafe是一个轻量级的,零依赖的库,用于处理Java 8+中的故障,并具有用于处理日常用例的简洁API和处理其他所有内容的灵活性。它通过将可执行逻辑与一个或多个弹性策略包装在一起来工作,这些弹性策略可以根据需要进行合并和组合。当前策略包括重试,超时,Fallback和CircuitBreaker。
5.forking
并行调用多个实例,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过 forks=”2” 来设置最大并行数。通过 timeout=”1000” 来设置调用超时时间。
forking的实现逻辑:计算目前需要的并发数,通过负载均衡算法选中被调用实例列表,并发地调用实例列表,并将处理结果成功的放到阻塞队列中,获取处理结果队列中的第一个结果,判断是否是异常,是异常则抛出,不是异常则返回结果。