一、主题分享

hello,大家好!我今天讲的不是什么高深的技术或者产品设计,只是前一段时间发生的真实的上线过程。大家就权当我讲一个故事。里面涉及的技术也比较简单,请大家可以不吝赐教~

1.背景

公司要上线支付系统V3.0,主要增加复式账系统。新老版本不兼容。即一笔支付交易必须完整走老系统记账或者走新系统记账。

数据库的主要影响是在已有的核心表(3kw)增加若干字段。数据库全部使用MySQL InnoDB引擎。整个上线的过程非常惨,折腾了一晚上。

2.升级过程

凌晨2点到7点,5个小时的上线过程中,经历了无法完全屏蔽流量、数据库导入主键冲突、上线步骤遗漏、隔离的UAT环境和配置更新复杂、MySQL5.5和5.6不兼容等问题。

3.上线过程

以下按时间发生顺序介绍上线过程。 为了方便叙述,我们假定D日为正式上线日,D-2日是指上线前两天。

3.1 D-2日

RD、QA决定上线,RD开始评审上线CheckList,我们称为CheckList A。大家一致认为直接在核心表增加字段风险较大,因为表非常大,而且生产机器数据库磁盘不是SSD。

实测,按我们生产环境的机器配置,一个3kw的表,加一个字段,大概需要20分钟,这次上线涉及4个这个量级的表,这个时间显然不能接受。

MySQL5.5 即使是pt-online-schema-change也非常难用,已经有过教训。不停服务升级无法完成kw级大表的schema变更。

pt的主要问题在于pt太慢了,整个过程会建很多的触发器,相当于SELECT出来再INSERT进去。另外一个问题是,业务数据库访问比较频繁,抢锁比较严重,pt抢不到锁反而会加重负担,也影响整个改表体验。

其实MySQL5.6官方已经提供了Online DDL的解决方案,除个别情况外,原生的Online DDL都是最优的选择。 mysql 5.6 原生OnlineDDL解析,但是我们当时的生产环境数据库还是MySQL 5.5,所以还是用不了。

讨论后的建议方案是

由于涉及到记账,这次上线比较重要。对于业务功能验证,希望完全暂停线上流量后,部署一个隔离的UAT环境,使用真实数据,供QA进行线上验证。也就是说,我们要针对这次上线手工打造一个UAT环境。(环境的配置是个大坑,也是后面无数问题的缩影)

3.2 D-1日

按既定方案,SYS和RD进行了完整的预演,主要是数据库操作。由于涉及模块多,上线步骤复杂,SYS对RD的上线CheckList从方便操作的角度进行了优化,生成了CheckList B。(注意:这里区别于前面的CheckList A,是SYS又搞了一个上线CheckList。)

数据库建议方案从实践上看是没问题的,但是由于数据库过大,实际耗时需要1个小时左右。4个3kw左右的表,一共加二十多个字段,1小时搞定。

QA利用预演环境(区别于UAT环境的点只在于不是真实数据)进行了业务功能验证,无误。晚上9点开始,给用户推送支付功能升级的大字报。D日凌晨2点到5点停服维护。

3.3 D日

凌晨,某会议室,RD负责人,QA负责人,SYS。

0点~1点半

SYS牵头进行了第二遍预演。过程遇到了数据库导入主键冲突问题,但是重试后解决。当时并没有定位原因,只是感觉很奇怪。

凌晨2点

SYS开始按操作步骤摘流量,屏蔽生产环境流量。但是发现按步骤都操作完了,数据库仍然有新的连接进来,即使强制杀了数据库连接,还有新的。完全不符合预期。(后来发现是一些年久失修的离线作业)为确保数据一致性,祭出大杀器:FLUSH TABLES WITH READ LOCK,见到数据库连接写阻塞的就kill,读链接无所谓。

新的数据库已经准备好,新的schema也更新好了。现在开始做数据库导入,执行了半个小时,挂了。导入主键冲突!可是怎么可能会有主键冲突呢?真是墨菲法则啊。第二遍预演遇到的问题,到正式执行的时候又碰到了!!刚刚从线上库导出来的数据,不应该有主键冲突的啊!

这是整个上线的第一步,当头一棒,就挂了!

凌晨4点
排查了一遍,怀疑是预演过程中,有QA的程序一直在跑自动化Case导致的。断掉QA的连接,重新执行数据库导入,导入成功。等数据库执行完,已经是4点了。(第一步导库,我们就比预期多花了一个小时。)

SYS配置了UAT的APP接入域名,QA开始打APP包进行验证。包打好了,但是安装后直接crash,无法打开。这次倒不是大问题,经排查,是因为QA配置Jenkins任务时参数填写错误导致。重新打包后,APP打开正常。

但是发现每一步都不顺的时候,真正的不顺可能才刚刚开始。

这种通宵上线,其实大家是有压力的,发现每一步都不顺时,每个人心里都开始有一些变化,但是当时又不好沟通。

凌晨4点半

ready了,后台服务上完线了,开始进行业务功能验证。此时是凌晨4点半。

尽管在预演过程中,业务验证非常顺利,但是在生产过程中,业务验证非常不顺利。基本上每个场景都走不通。QA做了冒烟测试,每个场景都不通。但是在预演环境时,都没有问题啊!那么这只有一种解释,环境配置有问题。

RD负责人开始逐个排查问题,由于涉及到网关、业务入口、支付核心、账务等各个模块,即使有LogTrace辅助进行日志排查,仍然非常耗时。LogTrace是我们自研的一个系统,可以根据一个logid串联起这个请求贯穿所有模块的上下文。

早上5点半

通了一些场景,又卡到一个关键的场景,业务验证不通过。

QA负责人从风险的角度开始打断RD,想要回滚。这时RD负责人压力非常大,觉得验证不顺利和代码没有关系,都是环境配置问题,涉及模块配置太多,很快就能解决。(这个项目组付出的太多了,连续一个多月的加班,每周单休,期间项目组成员还感冒,牙痛。)RD负责人知道项目回滚意味着什么,所以想坚持不回滚。但是QA Leader不依。

连续三次打断后,RD负责人不得不停下来交(chao)涉(jia),“到早上7点,有任何责任我背”。

这个过程中,牵涉最多的其实是环境和配置。我们有外网的接入网关,内部又有ESB网关,各个模块的调用非常复杂。

问题点如下:

每一个点,都是一个大坑。都不是什么技术难点,但是会阻碍场景测试。

为什么在验收的时候没问题呢?一到线上就有问题呢?

20171228_195705.png

早上6点半

主流程都已经没有问题了。

早上7点

正式对外切流量。

后续

公司对这个项目Review了三遍,从各个角度,项目的角度,开发测试过程,上线过程等。

结论

虽然最后项目惊险上线成功了,但是风险还是比较大的。如果7点还解决不了,回滚不但是项目组感情上接受不了的事情,会影响到公司正常业务,才是更大的问题!


二、 Q&A

Q1、这么重要的上线没有事先预演一次呀?
A1、没用的,毕竟环境不一样!而且UAT环境还都是现搭建起来的。
A2、在第二次出问题时就应该中止了!一般都会有同样的模拟环境。
A3、有预演过,预演的问题在于,预演环境的配置和真实生产环境不一致。

Q2、新老数据是否可以双写?
A1、双写的问题,不要做一致性校验啊,考虑过双写的方案。
A2、这样的方案有没有考虑过:存量数据迁移到新库 增量数据在一段时间内同步到老库,待验证没有问题后据情况下掉老库,避免双写,否则一旦出问题都不知道那个数据是正确的了。双写方案一般DB也是不建议做的。我们这边有几个方案,不过一般都是DB支持。

Q2-1、增加数据同步到老库上,这个一般怎么做?因为新老流程的记账模式都不一样。主要感觉这次上线时,最大的点在于,新老版本流程不兼容。又要保证数据强一致,很难有兼容的方案。
A1、比如通过binLOG将增量数据同步到新库。当然这里边是有一套基于binLOG的数据同步机制的。有生产端和消费端。生产端就是新库,消费端就是老库,不需要应用处理。DB层直接搞定。

Q3、这个和主从同步有什么区别?解析binlog?
A1、是的!


本文档来自支付产品技术交流群的聊天记录整理,由志愿者整理并发布到本网站。如需要及时收到来自支付产品技术交流群的最新消息,请扫码关注“凤凰牌老熊”的微信公众号。 本群面向支付行业的有经验(2年以上)的产品经理、软件工程师、架构师等,提供交流平台。如想加入本群,请在本文评论中留言(不公开),说明所在的公司、负责的工作、入群分享的主题和时间。