通用技术 记录一次亿级数据库源切换的测试范围梳理

Hugo · 2024年01月20日 · 最后由 Hugo 回复于 2024年01月21日 · 4197 次阅读

背景

简单的介绍背景,公司服务系统是流行的分布式架构。数据库之前经历了横、纵拆分表改造,这次决定把核心表迁移到分布式数据库(oceanBase)。服务与服务之间的调用就如同蜘蛛网一样错综复杂,如何保证这次优化上线后系统不出问题,是这次关键的任务。

团队前置的工作

  1. 切换方案评审
  2. 上线方案评审
  3. 测试范围评审
  4. 压测评审

下面主要介绍我这次梳理测试范围的思路

历史用例非常多,如果全量执行所有测试用例不仅耗时,而且未必能覆盖全面(有一些提供给第三方的接口可能测试不到)。功能回归远远不能证明这次测试的质量,以下是我这次梳理的一些思路

  • 运维平台
    • 运维的完善给我们提供了很大的便利,服务的调用关系都可以看得一清二楚,在运维平台上把这次改动服务的接口按流量从高到低导出到本地,按照二八原则把 80 % 流量覆盖完整就能保证业务能正常执行。但需要注意的是 20% 里面虽然调用量不大,但不代表不是核心流程接口,需要甄别。
  • 接口用例覆盖
    • 梳理了这么多接口,接下来就是对之前的接口用例查漏补缺的过程了,工作量的问题。。。。
  • 功能测试用例梳理
    • 在界面上测试一定是不能缺少的,虽然只是底层数据库切换理论上不会影响到上层接口调用,但小心为好
  • 代码覆盖率
    • 在这个场景下,代码覆盖率真的非常好用。使用接口自动化和功能跑一轮后,再梳理未覆盖到的逻辑,基本上基础功能就回归完成,而且通过这次覆盖率的检查,看到了一些冗余代码和一些功能上看不到的异常。在下面的代码中,keyManger.del(keys) 是永远都执行不到就跑到异常,但在界面测试的时候是完全无感知,也没有影响到业务
public Boolean removeCoursewareKeyByUserId(List<String> userIds) {
        try {
            List<String> keys = userIds.stream().map(it -> genUserCwCountCacheKeyV2(it, CoursewareState.AVAIL.getState())).collect(Collectors.toList()).stream().flatMap(List::stream).collect(Collectors.toList());
            keyManager.del(keys);
            return true;
        } catch (Exception e) {
            LOGGER.error("removeCoursewareKeyByUserId, userIds:{}", JSON.toJSONString(userIds));
            return false;
        }
    }
  • 异常场景补充测试
    • 这种大数据表切换过程中,都需要一些兜底的方案来保证事故发生后能正常降级或回滚。我们这次使用的是数据库双写的方案来保证数据和业务在出问题的时候能快速恢复。双写之前是在其他业务上已经验证过很多次,所以这次的异常测试的目标就有两个。第一就是验证读写切换的逻辑正确,第二就是验证在持续写后马上读的情况下,系统的表现(压测试也需要测试这个场景)
  • 流量回放
    • 流量回放也是我这次想用到的一些手段,但由于这次介入的时间有点晚,加上整个回放系统还有些坑要踩,就放弃了这个计划
  • 建群
    • 把这次涉及到的业务方拉进群里,通知相关方回归业务功能,有问题及时沟通

在做完以上的一些工作后,交付功能测试版本,后续的就是压测调优和线上回归的事情了。

如果大家有一些更好的测试方法和经验,希望可以分享出来一起讨论。

共收到 2 条回复 时间 点赞

你们也要开始迁移到 ob?其实有双写保障一段时间,这些问题都不会很大。改 ob 的坑也不是很多。

Hugo #1 · 2024年01月21日 Author
恒温 回复

是的,基本上没发现大问题。这次修改会有些代码的抽离,我的考虑就是尽量让流量打到核心业务接口通过,功能基本就没什么问题。

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册