关于灰度发布过程中表结构变动数据一致性的问题

4,529 阅读4分钟

0x01 灰度发布

先简单介绍一下灰度发布;摘抄自百度百科;

灰度发布(又名金丝雀发布)是指在黑与白之间,能够平滑过渡的一种发布方式。 在其上可以进行A/B testing,即让一部分用户继续用产品特性A,一部分用户开始用产品特性B,如果用户对B没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到B上面来。

0x02 如何实现

既然上面都写了一部分用户走老版本,少部分用户走新版本,那么肯定要从用户流量的来源网关层做控制;
网关层基本都差不多,但是灰度发布的业务需要自己来实现;实现起来还是比较麻烦的还需要动态的后台配置用户路由规则和比例之类的东西;

实现方案:XX云自带功能Nginx/OpenResty + LuaZuul + 代码Spring-Cloud-GateWay + 代码

如果我的灰度业务不复杂只是根据新的服务分发有没有啥偷懒的办法?直接上干货(IG永不加班) :Kong + Canary Release Plugin,详细的根据系统业务做灰度策略还是要自己实现
看名字和描述和知道是啥了,详细请看官方网站;

官方插件图

0x03 数据变动一致性问题及解决思路

准备工作

  • 灰度发布前根据公司情况做好全量或者增量备份做好回滚准备
  • 灰度发布的初始流量控制逻辑尽量先开放灰度测试账号,尽量避免用户数据错误

BUG导致

灰度发布前测试环境等应该做好严格的测试,防止轻易的bug导致数据不一致;你不可能出bug了马上回滚,让少量用户操作的数据直接丢失了;

业务逻辑变化导致

业务逻辑变化导致数据的问题根本不应该到灰度发布这儿来考虑,因为业务既然变化,说明以前的数据全都有导致问题,并不是灰度发布过程中一部分用户导致的问题;

增删改字段表结构变动导致

如果本地迭代没有数据库的变动当然迁移就很普通慢慢释放流量到新的服务;但是如果比如某个表的数据结构有变更动,两个版本同时操作会导致数据不一致的问题;如何解决;
以下纯个人想出来的思路,不敢保证100%没有问题
这个问题看似很麻烦,但是仔细落地想一下,数据表结构变动无非增、删、改字段,三种情况单独分析一下如何解决;

  • 增加字段:直接增加一个字段,新的微服务直接使用,老的微服务继续操作,数据也不会受到不一致的影响;
  • 删除字段:对于新的微服务来说没有这个字段不用考虑,等待完全替换成新的微服务之后,在删除对应的字段(做备份);
  • 修改字段: 比如A字段修改成B,先增加字段B然后update b = a,把A的值全部赋值给B,新的微服务操作B字段,老的微服务操作A字段,等完全替换完成后,将发布之后的A字段的变更数据再update到B一遍,最后删除老字段(做备份)

tips:如果用MyBatis等框架写sql请避免如下操作:select *, insert values (),一定要指定字段;

核心操作其实就是增加和删除字段,但是MySQL5.6之前Online DDL是非常消耗性能并且会阻塞写的,生产环境肯定是不允许的;

流程:创建新的临时表 --> 原表加写锁 --> 临时表修改 --> 数据源copy到临时表 --> 释放原表写锁 --> 删除旧表重命名新表

还好MySQL从5.6版本开始支持Online DDL,在5.7得到更大的支持,在8.0实现了部分操作的高效性! 支持快速加列、不阻塞写操作等;详细请看:developer.aliyun.com/article/715…

其他复杂场景

大公司一些非常复杂的业务场景都要停机维护(见过淘宝半夜停机维护页面)。愿意有空折腾业务也不是特别复杂,可以用数据库跑多个版本,同时用数据同步技术做好同步规则;

附:Online DDL版本变动图

变更图