前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一次支付系统升级过程经验教训分享

一次支付系统升级过程经验教训分享

作者头像
企鹅号小编
发布2018-01-08 10:50:11
9230
发布2018-01-08 10:50:11
举报
文章被收录于专栏:应用案例应用案例

一、主题分享

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

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,所以还是用不了。

讨论后的建议方案是

重新部署一套数据库(磁盘使用SSD),在新数据库上线建好更改后的schema,然后暂停线上流量,将全库数据用mysqldump出来,再load到新数据库中。

暂停线上流量再导出数据库,是为了保证数据一致性。(目前我们没有读写分离,而且保留只读功能意义不大)在新库上建好更改后的schema再导入,这样性能瓶颈就是数据库的写入INSERT。而不是数据库的ALTER。实测在kw级MySQL表上效率更高。

解决了数据库加字段的问题,后面就是业务验证的问题。

目前公司还没有完善的UAT环境(User Acceptance Test,可以理解是完全和生产环境一致的环境,即连正式的数据,正式的API,但是不对外发布,一般是内部业务验证的最后一步)。

由于涉及到记账,这次上线比较重要。对于业务功能验证,希望完全暂停线上流量后,部署一个隔离的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网关,各个模块的调用非常复杂。

问题点如下:

由于CheckListA 和CheckListB不等价;

有一些上线步骤被遗漏

UAT环境如何管理;

新部署的MySQL5.6 mysql.ini和MySQL5.5不一致导致代码不兼容

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

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

因为我们想手工造一个UAT环境出来,又要考虑到回滚方案(一旦决定回滚,如何快速的将所有的配置还原)里面涉及大量手工改配置的地方。

本来配置都有配置服务器管理的,因为我们要手工改这些配置,就会造成生产服务器和配置服务器不一致,要人工在黑板上记住都改动了哪些。(这是第二块黑板了。。。)

早上6点半

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

早上7点

正式对外切流量。

后续

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

结论

凌晨上线未必是好的选择:虽然凌晨是业务流量低峰,但也是人大脑活动的低峰,难以保持兴奋。像中间漏配置;真实进行UAT验证时,接入网关配置没有打开,这种低级别错误就很难解释。特么这么简单怎么可能忘啊!

做好充分的停服预告: 整个上线过程,太过仓促,停服时间超过预期,也没有充分评估用户影响。停服并不说明方案的设计不好,停服并不是什么丢脸的事情。

RD 一开始的上线方案评审想不停服,觉得停服好像非常shame。但其实不是,保证账务不出乱子,用户能正常完成业务功能才是最重要的。停服没什么大不了的。

做好止损红线: 各方提前沟通明确方案和时间点,什么时候冲,什么时候停。将在外君命有所不受。事先没有约定的约束,在方案执行中不能提,只会增加扯皮的谈资,没有意义。(会上可以随意发表意见,一旦会议打成一致意见,会议纪要一发,就不要再提意见了)

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

分享嘉宾非常详细地描述了上线过程中碰到的各个问题,最后给出一些忠告。 对支付研发而言,每一个坑都要用资金去填平的。仁者见仁,欢迎大家留下您的建议。

二、 Q&A

Q1、这么重要的上线没有事先预演一次呀?

A1、没用的,毕竟环境不一样!而且UAT环境还都是现搭建起来的。

A2、在第二次出问题时就应该中止了!一般都会有同样的模拟环境。

A3、有预演过,预演的问题在于,预演环境的配置和真实生产环境不一致。

Q2、新老数据是否可以双写?

A1、双写的问题,不要做一致性校验啊,考虑过双写的方案。

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

Q2-1、增加数据同步到老库上,这个一般怎么做?因为新老流程的记账模式都不一样。主要感觉这次上线时,最大的点在于,新老版本流程不兼容。又要保证数据强一致,很难有兼容的方案。

A1、比如通过binLOG将增量数据同步到新库。当然这里边是有一套基于binLOG的数据同步机制的。有生产端和消费端。生产端就是新库,消费端就是老库,不需要应用处理。DB层直接搞定。

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

A1、是的!

本文来自企鹅号 - 凤凰牌老熊媒体

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文来自企鹅号 - 凤凰牌老熊媒体

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档