
发布灰度解决了「新版本代码的小流量验证」,但服务端还有第二个灰度维度经常被忽略:数据灰度。新版本的接口写库结构和老版本不同、新功能的写入不能污染老版本的读、压测流量不能碰真实数据——这些都要求数据按「颜色」隔离。灰度发布的完整方案 = 流量灰度(谁进新版本)+ 数据染色(新版本的读写落到哪)。本文讲数据染色的完整设计。
流量按用户比例切到新版本后,新老版本是同时在线的,它们共享同一个数据库。三种情形决定了是否需要数据染色:
双写兼容:新版写数据表新增字段/新增表,老版读不到新字段但写入不受影响。这种情形不需要染色——新老写同一个表,新版本的字段老版本无视即可。这是最常见的兼容形态,靠数据库向前兼容性解决。
数据结构变更:新版的数据格式与老版不兼容(字段语义变化、分表路由变化)。此时新老版本必须写不同的数据集——老版读老表、新版写新表,这就是数据染色的硬需求。
流量性质区分:压测流量/灰度用户的写入要与生产数据隔离(压测数据进影子表),本质也是染色——流量被标记为「压测色」,写入路由到影子数据集。
判断用哪种情形的方法:发布评审时问一句「新老版本同时在线的窗口内,数据是否互相兼容」。兼容则只做流量灰度;不兼容则数据染色必做。
数据隔离的前提是流量被标记。标记的方式:
入口标记:网关按规则(用户尾号/白名单/请求头)给请求打上灰度标记(header 如 `x-gray: new`),标记随上下文透传全链路(RPC 框架的隐式传参、HTTP header 透传)。压测标记(`x-test-flag: 1`)同理。
标记的透传纪律:异步任务(MQ 消息、定时任务、线程池)是最容易丢色的环节——MQ 消息体里要带标记字段(消费者看到标记继续路由影子数据),线程池任务要把上下文复制到任务里(阿里 TransmittableThreadLocal 解决的是上下文跨线程池透传)。染色链路的任何一环丢色,数据就会写到错误的数据集——这是数据灰度最常见的事故形态。
颜色的体系:生产白(正常流量)、灰度色(新版灰度用户)、压测色(压测流量)。三色的路由规则在配置中心管理,全局可查。
影子表:同库同 schema,表名加影子前缀(`shadow_`)。灰度/压测流量写影子表。实现层通常在 ORM 或分库分表中间件做路由拦截(ShardingSphere 的 HintManager、自研 DAO 拦截器),按上下文的颜色改写表名。影子表结构随发布自动建(发布流水线里加 DDL 同步步骤)。
影子库:独立实例承载影子数据,隔离更彻底(资源层面隔离,影子库的高负载不影响生产库)。成本是一套实例 + 同步维护成本。压测场景标配影子库(压测的高压不能打到生产实例),灰度场景影子表够用(灰度流量比例小)。
字段级隔离:不适合拆表的场景(消息、日志类 append-only 数据),数据行加颜色字段(`data_color`),读取按颜色过滤。缺点是生产表混入灰度行,忘加过滤条件就读串——不如影子表彻底,只推荐给无法拆表的历史场景。
消息队列的染色:MQ 的影子隔离是独立 topic(`shadow_order_created`)+ 生产端按色路由。消费组同样按色订阅。注意 MQ 的堆积和监控也要按色分开,否则压测流量把消费堆积告警打爆。
一个容易被漏掉的坑:灰度用户用新版写入的数据(影子表),他的请求如果被路由到老版本(回切、重试、异步补偿任务在老代码里跑),老代码读不到影子表的数据——「我的订单不见了」。三个处理手段:
a. 灰度用户黏住新版本:路由规则保证同一用户始终路由到同一版本(会话粘滞),这本来就是流量灰度的基本原则,数据灰度更强依赖它;b. 老版本读兼容:老版读逻辑带「读双数据集」的回退(先读生产表,空则查影子表)——只对查询类安全,写类逻辑绝不能;c. 异步任务的版本一致性:异步消费任务的代码版本与消息产生版本可能不同(消息积压后新版消息被老版消费),MQ 消息带版本号,消费者校验版本决定路由。
数据染色体系建好后的收益不只是灰度发布:全链路压测(影子库 + 染色流量)、新功能试运营(灰度用户的数据在新数据集,可以独立清理)、A/B 实验的数据隔离(实验组数据染色,分析时按色取数)。这是「一套基础设施,三个场景」。
建设顺序的建议:先从压测染色做起(压测流量的隔离需求最刚性、场景最简单——只有写隔离),跑通后再扩展到灰度发布的写读双向隔离(复杂度上一个台阶),最后接 A/B 场景。反过来做(一开始奔着全场景设计)通常死在第一版的复杂度上。
数据染色集成到发布流程的 checklist:1. 本次变更的数据是否向后兼容(不兼容 → 染色方案必须评审);2. 影子表的 DDL 是否随发布自动创建(新表/新字段的影子同步);3. 染色透传的异步环节(MQ、线程池、定时任务)是否全覆盖(压测环境全链路验证一次染色透传);4. 回切预案(灰度回滚时,灰度数据的处理——保留影子表让新版回读,还是清洗);5. 发布后对账(影子表与生产表的数据量比例符合灰度比例)。数据染色的事故几乎都出在第 3 和第 5 条——透传丢色和数据量对不上(影子写到了生产表)。发布演练时专门验证这两条,数据灰度就稳了。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。