3.5.2 故障检测
容错处理的第一步是故障检测,心跳是一种很自然的想法。假设总控机A需要确认工作机B是否发生故障,那么总控机A每隔一段时间,比如1秒,向工作机B发送一个心跳包。如果一切正常,机器B将响应机器A的心跳包;否则,机器A重试一定次数后认为机器B发生了故障。然而,机器A收不到机器B的心跳并不能确保机器B发生故障并停止了服务,在系统运行过程中,可能发生各种错误,比如机器A与机器B之间网络发生问题,机器B过于繁忙导致无法响应机器A的心跳包。由于机器B发生故障后,往往需要将它上面的服务迁移到集群中的其他服务器,为了保证强一致性,需要确保机器B不再提供服务,否则将出现多台服务器同时服务同一份数据而导致数据不一致的情况。
这里的问题是机器A和机器B之间需要对“机器B是否应该被认为发生故障且停止服务”达成一致,Fisher指出,异步网络中的多台机器无法达成一致。当然,在实践中,由于机器之间会进行时钟同步,我们总是假设A和B两台机器的本地时钟相差不大,比如相差不超过0.5秒。这样,我们可以通过租约(Lease)机制进行故障检测。租约机制就是带有超时时间的一种授权。假设机器A需要检测机器B是否发生故障,机器A可以给机器B发放租约,机器B持有的租约在有效期内才允许提供服务,否则主动停止服务。机器B的租约快要到期的时候向机器A重新申请租约。正常情况下,机器B通过不断申请租约来延长有效期,当机器B出现故障或者与机器A之间的网络发生故障时,机器B的租约将过期,从而机器A能够确保机器B不再提供服务,机器B的服务可以被安全地迁移到其他服务器。
需要注意的是,实现租约机制时需要考虑一个提前量。假设机器B的租约有效期为10秒,那么机器A需要加上一个提前量,比如11秒时,才可以认为机器B的租约过期。这样,即使机器A和机器B的时钟不一致,只要相差不会太大,都可以保证机器B的租约到期并且已经不再提供服务。