当我们在抢红包时,微信运维在做什么?

2,948 阅读20分钟
原文链接: mp.weixin.qq.com

作者简介

周汤 

腾讯 微信支付运维负责人

就职于腾讯-微信事业群-技术架构部-运维中心。2009年加入腾讯,先后负责过拍拍、网购、易迅、充值、团购等业务的运维工作。2014年转入微信,负责微信支付业务的运维工作。

一、背景

这图是2016年互联网女皇发布的互联网报告里的截图,左图是讲用户每月支付的频率,可以看到微信支付排在最前面的,大概每月支付超过50次,排在第二的是全美借记卡的支付次数。

微信支付单月支付次数大于全美借记卡+信用卡的次数总和,在这数据背后反应出移动支付时代的全面到来,同时也可以看出我们国内的移动支付,无论是产品、用户量、支付频率上,个人认为都是领先全球的。

互联网其他一些产品比如我们所知道的搜索、电商、即时通讯都是国外诞生,国内再做本地化后发展起来的,但是移动支付在国内的发展应该是一直领先国外的

右图展示的是2016年农历新年,微信支付的支付金额达到80亿人民币,看金额可能不够直观,我们看一下具体的背后技术层面的数据。

从监控上统计到的数据是支付峰值达到每秒15万次,拆红包大概是每秒50万次,这个业务量是非常巨大的,我个人认为这应该是当前全球最大的支付和结算系统。

我们看一下背后是什么样的环境来支撑这样的业务。传统支付很多都是直接上小型机+商业数据库;而我们直接采用 PC+MySQL 这种最互联网的做法,PC硬件的故障率比较高,从我们经验来看大概有2%左右;数据库软件我们也是使用的开源版本,少量的定制,没有购买专门的技术支持服务;排障、优化都是靠自己团队解决。

规模大概如下,设备一千多台,数据库实例一千多个,数据库业务500多个,但是我们 DBA 只有3位同学,所以压力和挑战还是非常大的。

这个背景下争取做到的几个目标:

第一个是高性能,我们现在日常的支付量大概每秒几万,传到数据库层面 TPS 应该是百万量级,在这样的环境下达到这个性能还是不容易的;

第二个是高可靠,产品业务特性是和金融基本上类似的,数据一致性不能有任何差错,有相当多的场景可能会导致不一致,比如红包拆了多次、重复支付、支付状态不准确等,最直接的后果就是导致平台赔付;

第三个是高可用,线下的商家、医院、服务场所、用户对支付可用性是非常敏感的,如果用户发一个微信、微博消息出现失败,客户端是比较容易做重试和延时处理,用户很少感知到,即使失败绝大部分可能忍忍就过去了,但是支付一旦出现失败,或者是用户、商户侧看到的订单状态不一致,我们基本马上就收到投诉,这个故障投诉比跟其他业务相比是天壤差别。

最后是安全方面,做为一个支付平台,这里有很多敏感数据,怎么保证不会被内部人员或者外部人员非法的查询和篡改,这个对我们也是一个很大的挑战。

总结挑战

PC硬件+PC开源软件平台下,每分钟百万支付、千万流水的业务量;业务高速成长,变更和迭代也非常频率,这也是和传统银行差别很大的地方;任何软硬件故障、运维不当都可能是百万级别的损失;所以我们DBA压力非常大,万一故障要赔钱可真心赔不起。

业界的《MySQL从入门到删库跑路》这些书我们还是希望DBA尽量不去看。这样的背景下怎么避免DBA跑路,怎么把数据运维质量做的更好?这是我们今天要介绍的主题!

二、DBCMDB

DBCMDB 个人认为这是数据库运维管理的基石,CMDB概念大家应该都比较熟悉,我认为应该是分三个层级:

  1. 基础 CMDB,这里存储的是IDC运维的基础配置,比如硬件、IP、物理位置等信息;

  2. 运维 CMDB,大部分做系统运维的同学都有接触和使用,里面存储的有程序、端口、任务、服务等等信息,这是逻辑层部署、扩容的关键配置;

  3. 数据库管理也应该有独立的 DBCMDB,存储业务相关的具体数据库实例、端口、库、表这样的信息。

只有在这些信息的基础上才可以开展DB的运维管理工作。

为什么做DBCMDB?

初创公司可能没有这样的烦恼,但是业务成长之后肯定有这样的问题,业务非常多,配置非常复杂,像我们刚才前面讲的上千台服务器,各种部署,比如一个业务分了多组,可能有的为了优化一台机器上运行多个实例。

一个实例上有很多库,各个业务分布分表又不一样,比如有的分 1000 表,有的分 1024 表,命名规则也不一样,这么复杂的配置关系,靠人工管理肯定是不足的。这种情况下,最基本的一个数据库表结构变更需求,你要找到准确的机器、实例、库、表都是个困难的事情。

除此外,还有些主动或故障带来的部署调整、业务调整,机器的具体用途都在动态的变化,这种情况下怎么保证调整之后,与之配套的变更、监控、备份是能同步更新?

怎么做DBCMDB?

首先需要存储一些基本核心配置,比如 IP、Port、业务、责任人,分表数量、主从关系等等。在这些基本信息之上还要提供友好、完备的Web界面管理工具。

下面是我们系统的一些简单的截图,左边是大概的关系模型,中间是我们的某个业务对立物理部署的树状型,右边是某个业务库表的情况。

DBCMDB到底能做什么?

有了 DBCMDB 以后,我们就可以基于这个配置数据,建设整套数据库运维工具和体系,后面给大家分享的能力也是基本此,比如可以建设自动化部署工具、变更、监控…,在线业务系统的 DB 连接配置,也是从这里获取的。

DB变更

变更类型非常多,比如切换、机器挂了或者是扩容之类的。移动支付也是互联网产品,迭代非常快,每天有几十上百个变更;这在传统IT行业上是不可能发生的,银行可能每周左右变更一次,我们是每天都是不停的变更,那怎么在这种快速迭代、不断变更的场景下做到类似银行的稳定性和可用性,这对我们来说是很大的挑战。

早期DB变更

早期我们人力很紧张的时候,都是开发人员直接连数据库进行变更的,相信很多初创公司也是这样场景,这里主要的问题。

一是专业度是不够的,没有数据库开发规范或是规范没法落地,每个开发人员按他自己的思路、做法来变更数据库,一些用法方面也不够专业,常常用学校的那套数据库设计理论来做产品,管理极为困难。

二是由于变更导致的故障频发,比如针对一些海量数据的表加个索引,可能就把线上系统搞挂了,或是 SQL 不严谨,经常出现数据误删误改的情况,非常头痛。

中期DB变更

后来我们做了个数据库需求系统,所有变更必须经过 DBA 审批后才可以执行,经过 DBA 后的变更在专业性、稳定性得到了明显提升,但是需求提上来后, DBA 还是需要花很多时间和精力去评估需求,沟通成本非常高,同时这阶段 DBA 也还是手动执行,效率是非常低下,不少变更需求会在凌晨进行,DBA 同学都非常辛苦。

现在的DB变更

现在我们把这工具做成DB变更系统,首先所有变更开发自助提单,提单过程是基于前面讲的 DBCMDB,从 CMDB 选出所属业务,库表,物理部署这些信息,以及表的数据量级等信息,再给出一个 SQL 语句,最终执行还是 DBA 来做,DBA 会评估这个 SQL 是否合理,并且制定一个执行计划。

简单介绍一下我们执行计划上的一些能力,因为我们现在业务量非常大,白天业务高峰期变更,DB 性能影响还是比较大,DB 访问上升几十毫秒就有一堆告警和反馈了。

所以大多变更都在业务低峰期实施,我们现在基本做到了凌晨无人执守的数据库变更,另外变更时我们也能精确控制灰度、并发度,以及执行间隔,借助这些手段,基本保障了变更对数据库性能的影响,变更这块的质量、效率也得到了一个比较好的提升。

三、DB监控

早期监控

监控是 DBA 的眼睛,没有监控数据的话我们无法掌握数据库的健康状况。最早我们是使用 Nagios、Zabbix 这些工具来实现,确实也可以解决很多问题,监控点是比较全面的,基本上想到的都有,功能也比较完备。

但是在管理上挑战就比较大,我们业务比较多,比如上千个实例,经常加、减配置,使用这些工具配置漏了很难发现也容易出故障,比如今天做数据便变更,但是忘记加监控,哪天 DB 性能有问题是完全不知情的。

另外就是缺少监控告警后的事件跟进处理能力,告警出来后有没有跟进处理,处理进度如何都是不清晰的,历史上我们曾经出现过一个比较严重的事故。

我们有一批DB业务量涨的非常快,磁盘快满已经告警出来,然后DBA同学赶紧处理了,但是遗漏处理了一组,他自己没有发现其他人也没有发现,监控系统也没有发现因为还是在故障中所以没有持续告警出来,结果过两三天之后磁盘直接爆掉了。

还有就是我个人认为这些国外的开源的产品,在用户体验和UI方面,国人使用起来还是不够顺畅的。

现在的BD监控

我们现在自建了整个数据库监控系统,从底层的 Agent 到存储、告警,全部自己开发。重构的设计也是基于前面讲的 DBCMDB,管理有了很多的优化,后续的部署调整只需要对 DBCMDB 更新,监控系统自动适配,基本不需要频繁的操作和修改监控配置。

告警策略上也做了很多优化,不再针对单个IP级别去配置,而是配置一些策略模板,再将模板应用到业务上;监控数据采集上来后,通过一系列的换算找到某个 DB 应用哪些告警策略,极大的简化了策略的配置管理。

还有前面讲到完备的事件处理流程,就是针对前面说的类似事故,告警后会有持续的事件跟进,所有告警、预警分级处理。

告警产生后会由事件系统跟踪确保异常能够及时无误的得到处理,比如五星级告警,我们要求 DBA 需要在5分钟内响应,30分钟内处理完成,如果处理超时就会有自动上升和通知到更多的人关注。

四、数据安全

整体安全

任何一家公司的数据安全都是企业的生命,数据泄露或者丢失对任何企业、业务带来影响都是不可估量的。

大概介绍一下我们整体做的事情:首先主机层面,我们数据库只能从专门跳板机要登陆,非授权人员无法登录服务器,DBA 所有的操作都有记录和审计,如果有风险的操作会预警出来。

监控方面,一般 MySQL 攻击都会尝试登录,攻击者都会扫描猜测密码,我们可以在这个阶段就能有效的发现,现在特别监控非法连接,如果账号、密码错误的登录,不在授权管理范围之内我们马上告警出来,就可以跟进分析真的是业务用错了,还是有人在攻击。

授权方面我们基本上是最小化按需授权,非常精细度控制,这个后面会给大家介绍。还有业务上需要针对一些关键数据作保护,比如账户余额这个字段,如果内部人员想给自己加钱,是否直接一条 update 语句,就能从一百块变成一百万呢?

程序上、技术上需要防止内部人员干这些事情,就要有防篡改和校验的能力。此外还有一些安全扫描和开发规范,及时的发现和规避一些类似 SQL 注入这样的高风险漏洞。

还有备份,脱库大部分是来自于内部的,在职期间把数据库备份拉下来存硬盘里,离职后往业界一放这个影响非常大的,那怎么防止这个事情?

这个很难绝对防,只能不断加固,我们现在所有备份都是加密的。通常备份存储有很多人可以接触得到,加密备份就是防止其他人员、业务人员拿走。再就是规范上的从管理、实践上约束这些人不能尝试做这些事情,技术只是手段。

授权系统

再看一下授权,以前授权是开发提需求,DBA 逐IP手动执行。主要问题有效率低,每次上线、扩容都需要操作。权限容易遗漏、容易出错,扩容时提供的密码与原密码不同,只管授权,没有回收,权限被放大。

我们现在是建设授权系统来管理,思路是这样的:基于业务模块加业务DB来管理权限,系统自动根据 CMDB 换成IP来授权,部署调整无须手动变更权限。另外与发布系统联动,废弃权限做到了自动回收,基本解决了我们前面讲到的一些问题。

五、高可用性

数据库高可用性

通常会分两个层级来做,一个是数据库层,一个是业务层。先看一下数据库怎么做。这是我们的主从自动切换工具,我们会在每个 MySQL 前面运行一个 HAProxy 来做 TCP 转发,将写请求转到真正的 Master 上面,在每台 DB 服务器上都会运行一个 Agent 来监控 Master 的存活状况。

如果所有Agent都判断Master挂了,我们就会通过etcd存储来决策切换,由Agent来负责调整主从关系以及TCP转发设置;这个工具非常专注,只做快速自动切换,完全兼容现有部署、运维方式,升级回退也相当容易;同时具备三机读写、三园区容灾等特性;稳定和可靠,有效解决这种单机硬件故障的问题。

另外我们目前其它团队也在开发 PhxSQL 组件,这个比前面的方案改动更大一些,会在 SQL 同步的中间加一个强大的、完全一致的队列解决数据一致性的问题,所以它的主要特点是强一致和快速切换。

业务高可用性

业务上怎么应对DB故障的问题,光有数据层防范还是不够的,我们要求无论DB 发生什么事情,业务层都要能活下去,不能完全信任 DB,DB 也有很多不可预期的事情,DBA 也控制不了。

所以我们的研发团队推出了一个跳单的方案,这个只适用于ID内部生成的,且不需要连续的场景;当前我们的订单库就是这样处理的,首先数据库分成很多组,比如几十组,每组都是可以读写的。

如果某组 DB 故障,读写失败后,业务层会把这个状态信息反馈到上面,上层在分配 ID 的时候可以根据状态做调配,自动跳过故障号段,这个好处是可以快速的让业务继续跑下去,新的支付订单完全不受影响,而老的订单读写的可用性对支付体验影响较小。

六、Golang

简单介绍一下 Golang,我个人认为非常不错推荐给大家。以下是它的一些主要特性:

  • 首先是来自谷歌,由一堆大神级人物开发的;

  • 语法简洁、清晰、高效,性能非常强大,跨平台,基本能做到同样一份代码能跑在多个平台上;

  • 我们之前的开发语言绝大多数是单机单核时代的产物,针对多核的使用,大部分是通过多进程或是操作系统的多线程之类的能力来做的,但是 Golang 语言本身就是在多核的前提下设计和实现的,对高并发和分布式都有很好的优化;

  • 还有自动垃圾回收,和 JAVA 的功能类似,目前国内最大的 C++ 开发团队应该是在腾讯,开发人员的水平也是参差不齐的,在内存泄漏方面还是很难做到杜绝,所以还是能看到程序运行多少次后通过重启来规避内存泄露的现象;

有这个 GC 能力后,开发同学就相当轻松了,基本不需要管理内存分配和回收;还有强类型、静态编译,内制高级类型,还有本地程序,部署非常简单,这个是我最喜欢的地方,没有任何依赖;堪称互联网语言,所以里面内置了大量网络通信、加密、解压缩、数据库的类库,基本语言内部把这个活给干了。

所以我个人对它的总结就是:拥有 C/C++ 级别的性能、稳定性、部署便捷性,以及拥有 3P、Java 等语言的易用性和高级语言特性。

对于使用场景,应该适用于绝大数分布式后台型的业务、可以用Java的地方就可以用它,但是它的性能和易用性我个人觉得比 JAVA 优秀。

还有一种特别场景,假设你是一个软件开发厂商,你想保护自己的代码不被反编译出来,目前来看用 3P,Java 之类的是比较困难的,有相当多的工具可以反编译出源码。

用 C/C++ 可以很容易做到,但是开发效率比较低下,对开发人员要求也比较高,招人也不容易,用 Golang 就非常有优势了,简单、高性能,还能防止反编译。

Golang 当前发展也比较快,业界也有相当多的一些软件在使用,我们可以看到的有 Docker、Etcd、Nsq,一些新的项目慢慢倾向于用它开发。我的团队也有比较多尝试,比如外网质量监控,DB 监控,DB 快速切换都是用 Golang 开发的。

Q & A

提问:刚才你讲的 Golang 跨平台比 Java 好,到底是怎么实现的?

周汤:两者的跨平台实现有些区别,Java 是编译成中间字节码,再由Java虚拟机来解释执行,不同平台同的 Java 虚拟机实现是不一样的;而Golang是直接编译成目标平台的机器码;个人认为在部署角度上,Golang 更方便一些;

提问:刚才你说的有一个问题,经常有很多业务创建一些账号权限之后,业务下线很多还有人用,这方面有什么好的经验和工具吗?

周汤:这个就是权限管理的深度问题,不管是 MySQL 还是网络策略,很多公司和业务都是只管授权,没有回收的。我们的做法是授权的时候不是IP粒度的,而是业务粒度的,部署有调整的时候会重新计算权限并进行回收;

提问:是业务下线或者迁移账号就清除了?

周汤:部署系统发生调整后,会调用授权系统接口,如果上线做授权动作,下限就把权限清理。这些能力和工具都是需要自己建设的,目前还没有一些通用的工具可以用,但这思路可以借鉴;

提问:刚才你最后讲的,用 Golang 程序开发语言,用什么样IDE,Window 有 Window 的程序,  他们不同环境下,是怎么样做的?

周汤: Golang 语言本身比较简单,代码的组织结构和目录结构都比较清晰,你可以用所有的文本编辑器来开发,但效率相对低一些,目前有相当多的IDE已经支持 Golang 的开发,这个在网上很容易搜到,比如 Vim, Eclipse, Visual Studio;另外也有一个专门给 Golang 定制的IDE叫 LiteIDE 比较简单易用,我主要用这个,这个 IDE 在 Windows 和 Linux 都可以使用。

Golang 同一份代码,可以在不同的平台编译出对应平台的二进制执行程序,甚至可以跨平台的编译。基本是一个命令就可以搞定。

近期好文

《360网络运维自动化演进之路》

《广发银行:Docker 适配传统运维的那些事》

《全链路压测军演系统 — ForceBot》

还有更多BAT的资深运维汇集GOPS · 深圳站

腾讯游戏蓝鲸产品总监、腾讯SNG运维专家、阿里游戏运维负责人、百度敏捷教练...... 不容错过的阵容和演讲,带你领略运维前沿技术。

GOPS2017·深圳站

GOPS在2016年从深圳出发,当时门票提前几周收盘,一年之后承载着运维人的期望,GOPS再次来到了深圳。

  • 会议地点:南山区圣淘沙酒店(翡翠店)

  • 会议时间:2017年4月21日-22日