
5.3 缓存集群升级场景
很多初创团队的蛮荒期,并没有完整的底层服务。
团队在初建时业务体量不大,在预估的系统服务 QPS 较低、系统压力较小、并发访问量少、近一年没有大动作等条件下,结合快速起步、时间紧迫、成本投入的因素,并不会投入特别多的研发资源构建出非常完善的系统架构。如图5-3所示,就像对Redis的使用,可能最开始只需要一个单机就可以满足现状。但随着业务超预期的快速发展,系统的负载能力也要随之跟上,原有的单机Redis已经无法满足系统的需要。这时就需要建设或者更换更为健壮的Redis集群服务,在这个升级的过程中是不能停系统的,并且需要平滑过渡。

图5-3
随着系统的升级,可以预见的问题有如下几种:
·很多服务用到了Redis,需要一起升级到集群。
·需要兼容集群A和集群B,便于后续的灾备,并及时切换集群。
·两套集群提供的接口和方法各有差异,需要进行适配。
·不能影响目前正常运行的系统。
虽然升级是必须要做的,但怎样执行却显得非常重要。
5.3.1 场景模拟工程

在以上的场景模拟工程中,包括了如下信息。
·在业务初期,单机Redis服务工具类RedisUtils主要负责的是提供早期 Redis的使用。
·在业务初期,单机 Redis 服务功能类 CacheService 接口以及它对应的实现类CacheServiceImpl。
·随着后续业务的发展,新增加两套Redis集群EGM、IIR,作为互备使用。
接下来分别介绍三个Redis服务提供的缓存功能,以及初期的使用方法。同时需要注意这三套Redis服务在使用上会有一些不同,包括:接口的名称、入参的信息,这些也是在使用设计模式时需要优化处理的要点。
5.3.2 Redis单机服务RedisUtils


首先需要注意一点,我们是使用Map模拟Redis的相关功能,这样比较方便测试。这里把关注点放在架构设计上。
5.3.3 Redis集群服务EGM

这里模拟第一个Redis集群服务,需要注意观察这里的方法名称及入参信息,与使用单体Redis服务时是不同的。有点像A用mac系统,B用Windows系统,虽然可以做一样的事,但操作方法不同。
5.3.4 Redis集群服务IIR

这是另一套Redis集群服务,有时在企业开发中可能有两套服务做互相备份。这里也是为了模拟,所以添加两套实现同样功能的不同服务,主要体现抽象工厂模式在这里发挥的作用。
综上可以看到,目前的系统中已经在大量地使用Redis服务,但是因为系统不能满足业务的快速发展,因此需要迁移到集群服务中。而这时有两套集群服务需要兼容使用,又要满足所有的业务系统改造且不能影响线上使用。
5.3.5 模拟早期单体Redis使用
接下来介绍在模拟的案例中,对单体Redis服务的使用方式。后续会通过两种方式将这部分代码扩展为使用Redis集群服务。
1.定义Redis使用接口

2.实现Redis使用接口

目前,Redis使用的代码比较简单,在一些体量不大的业务场景中不会有什么问题。但如果体量增加,改造升级的过程就会比较麻烦。因为此时所有的业务系统都有同样的使用方式,所以如果每一个系统都需要通过硬编码的方式进行改造就不那么容易了。此时,可以先思考怎样从单体Redis的使用升级到 Redis 集群的使用。