代码中如何应对缓存服务器宕机的情况
今天在演练这样一个场景——假如所有缓存服务器都宕机,而且不能很快恢复,并且假设数据库服务器能够支撑,在代码中如何应对这样的情况?
之前的做法是在读缓存的地方捕获异常并写入日志,然后直接从数据库读取数据;在写缓存的地方捕获异常并写入日志,继续后续处理。这样看起来不错,虽然缓存服务器宕机,但程序可以继续工作,虽然速度慢一些,但不会让网站服务中断,然后只要把缓存服务器恢复即可。
但是如果缓存服务器宕机时,访问量很大,每一个操作缓存的地方都抛异常、写日志,这是两个开销很大的操作,大量的这样的操作会给Web服务器带来很大的压力。有没有更好的解决方法呢?
当操作缓存时抛出了第一个异常,我们就已经知道缓存服务器发生了故障。接下来对缓存的任何操作不仅没有必要,而且由此产生的异常会带来额外的开销、影响性能。只要我们通过一种方式在知道缓存服务器发生故障的第一时间通知后续缓存操作代码不要进行缓存操作,就能解决这个问题。
我们想到的一个解决方法是通过全局静态变量,该全局静态变量保存缓存服务器当前可用状态,只要有一个操作缓存的地方出现异常就将该变量置为不可用状态,并写日志、发通知。每一个操作缓存的地方在操作前先检查一下这个全局静态变量,一发现缓存服务器不可用,就放弃操作缓存,进入无缓存情况下的操作流程。当我们得知缓存服务器宕机后,先专心把缓存服务器恢复正常运行,然后更新一下这个全局静态变量即可。
这又是一个看起来不错的解决方法。但是全局静态变量只能在当前应用程序的当前进程中全局,无法在Web Farm(比如使用负载均衡,同一个应用程序运行于多台服务器上)与Web Garden(同一个应用程序运行于同一台服务器的多个进程中)的场景中全局。所以采用这个解决方法,缓存服务器宕机时,每个进程都要进行捕获异常、设置全局静态变量的操作,虽然不是最佳解决方法,但总比异常满天飞要好很多。还有一个更头疼的问题,就是在缓存服务器恢复正常后,如何将这些全局静态变量恢复为可用状态?无法代码进入每一个进程中进行操作,目前我们只想到一个解决方法——重启应用程序(如果是IIS,回收应用程序池)。
有没有更好的解决方法呢?继续思考,也期待你的良计妙策。
【更新】
改进修改全局静态变量的方式,通过定时执行的代码检查缓存服务器的状态。如果缓存服务器不可用,将全局静态变量置为不可用状态;如果缓存服务器可用,并且全局静态变量的值为不可用状态,则将全局静态变量置为可用状态。