本文由 dbaplus 社群授权转载。
大家好,我是工行数据中心负责 MySQL 数据库的顾龚磊。我们工行使用 MySQL 的时间很短,从 2017 年才算真正使用,在我们数据库专业组之前分为两个组,Oracle 组和非 Oracle 组,MySQL 在我们行内以前是一个很边缘化的数据库,但是随着业务的演进,包括 MySQL 架构转型,MySQL 慢慢走上了舞台中央。
今天我想跟大家分享 MySQL 本身在工行的实践经验,主要跟大家分享四个主题:第一个为什么走向分布式?早上也听到几个大佬说分布式的架构,我们现在用的架构就是他们口中相对比较落后的架构,因为银行业比较追求稳定,所以会使用很稳定很成熟的架构。
一、为什么走向分布式
首先说一下大背景,我们行 2017 年已经提出核心业务需要灵活的平台,何为核心业务呢?大家平常接触到存贷款、信用卡等业务,这些银行真正核心的交易要求有更灵活的平台支撑,以及在 2018 年新增一些业务,比如物联网、人工智能等一些都必须直接上开放平台。
这样的政策调整对我们影响还是非常大,传统银行业架构在核心业务层面是 DB2+WAS,在平台层面是 Oracle+WAS,这两个架构本身在我们行内已经运行快十几年。它运行本身是非常稳定的,但是在整个背景政策调整的下以及业务规模增长趋势下,我们发现纵向垂直能力已经无法满足业务的增长,同时伴随业务规模增长,开发侧已对应出现变化,实现敏捷迭代,而从运维层面对于敏捷交付这块面临比较大的挑战。
行内大多数一些核心的交易 7×24 小时,业务特点是短平快,对传统的架构提出了巨大的挑战。在成本控制方面,由于核心业务涉及商业化的软件上面需要投入较多 License,所以我们整体的成本是无法降低的。
数据库在 IT 设施基础当中是比较核心的,因此在这样的背景下,我们的数据库面临转型势在必行。
从业务支撑的角度,我们发现单库已经无法满足、支撑这样的业务增长;从我们运维能力的角度,我们发现传统基础环境的供应以及运维模式都已经无法应对开发的这种敏捷迭代了;从风控角度通过打散数据,解耦各个业务层的依赖,降低集中式的风险;从成本角度通过核心业务使用更廉价的硬件基础设施有效降低成本,自主可控,解决对商业产品的过度依赖。
二、为什么选择 MySQL
为什么使用 MySQL?实际上我们对开源业界的数据库都做了一些调研,最终我们还是选择了 MySQL,我列举了以下几点。
刚刚说到银行是追求稳定、安全,MySQL 实际上在较多互联网公司有大量的实践经验,而且有较多的厂商作为贡献者参与到社区当中,整个社区是非常活跃的,Gartner 上常年稳居前三;MySQL 的版本质量也是相对稳定的。其开源的特性是没有 Licence,也相对自主可控。其轻量化的部署特性以及灵活扩展的能力也比较符合行内业务特点的需求,相较于同为关系型数据库 DB2 和 Oralce 相对容易上手,业界也有很多的成熟配套方案。综上结合我们行的一个自主研发为导向,以及更贴近行内业务特点、版本质量稳定,经过业界多年检验的数据库,所以 MySQL 就成为我们的首选。
三、MySQL 发展之路
我们行在这两年对 MySQL 发展推广比较坚定,大家可以看一下这张图。刚刚也提到在 2017 年的时候,我们 MySQL 主要用于办公类非核心类平台应用,总体规模不超过 200 个实例,但是随着 2018 核心业务的下移,平台整个 MySQL 使用量呈现井喷式增长。随着分布式架构下 MySQL 节点数的激增,我们发现机房密度不够,所以我们在 2018 年 10 月开始改造,大家看到 2019 年 5 月,我们实际上已有大概 600 个 MySQL 在容器部署。
怎样去管理大规模的 MySQL 摆在我们面前,因此我们引入了 MySQL 管理平台,通过这个平台可以实现安装部署、高可用、监控、备份、性能容量的管理,还有引入数据访问层。
数据库访问层实际为数据库中间件,我们使用了开源的 DBLE,引入 DBLE 可以简化开发的工作,提升开发的效率,其本身支持各种水平、垂直数据分片,以及支持跨节点的查询,我们是通过单园区主备部署保证高可用的,并在双园区进行双活部署,解决 DBLE 本身单点的问题。
DBLE 更多解决了开发层面的问题,而我们 MySQL 管理平台则面向运维。通过定制研发了 MySQL 客户端组件实现了环境自动化部署;性能数据地自动采集;监控实时上送;通过联动 DBLE 实现应用无感知地高可用自动化切换以及在非 DBLE 架构下,能够自动感知数据库异常进行自动切换,实现 RPO=0,RTO<60s 的业务连续性;并使用 MySQL 源生同步复制技术保证数据冗余。
四、MySQL 发展过程中的问题及优化
在 MySQL 的推广过程中,我们也确实看到了很多问题,我这边列举了几个我们认为比较经典的问题。
第一,行内传统架构数据库存储一般都使用盘机,我们一些 MySQL 业务特点是重 IO,重 IO 这些库,如果都连到一个盘机,很多时候在双十一电商春节这种活动,这个盘机是扛不住的,会出现 IO 争用。
第二,同城 RPO,这个异步方式同城 RPO 肯定是保不住。
第三,服务器资源利用率低,结合目前应用业务一个特点,我们 CPU 几乎是躺地板的,基本全年利用率 5%,主要吃内存,吃 IO,所以这就极大浪费服务器资源。
第四,备份存储节点的浪费,因为我们一主两从架构下会对每个节点去做存储的划分,但实际上真正备份只有一个节点,就是同城从库,这就导致了另外几个节点存储完全浪费,而且占用盘机的资源。
针对这些问题,我们逐一做了一些优化,对于 IO 争用问题引入本地 SSD,有效提升盘机的性能问题;对于服务器资源利用率低的问题,通过 MySQL 云化部署去提升我们服务器资源利用率;对于备份资源浪费通过对接 ceph 节约成本;对于高可用通过一主三从改造提升同城 RPO。
我先说一下高可用架构优化,这就是一主两从,应用服务器是通过域名方式连接数据库的,域名是绑定 VIP 的,通过 VIP 漂移实现本地切换,大家注意之前的架构是 ACK 降级,也就是说,这个架构下如果一降级就一定会存在丢数的可能。
因此,我们这边做了相应的改造,就是新增了一台同城从库是半同步,然后把原来的异步从库改成半同步角色,同时调整了 ACK。这样做得好处是什么呢?通过不降级能够保证数据的强一致,为什么 ack=2?是因为我们设计成所有从库,你有多少台从库减 1,就是它的 ack。这样做得好处是相当于每次数据同步,同城一定有一个库是拿到的,从这个方式保证了同城 RPO。
既然增加了一台从库,所以成本一定会增加。所以我们在去年 10 月份的时候开启了这个项目 MySQL 云化部署,通过 MySQL 云化部署,我们真真切切感受到倍率现在 4-5 的样子,也就是说通过这样的部署方式节省了应该有 400-500 台物理机。
那我们是怎么去做的呢?因为我们行内 PaaS 平台已经使用比较稳定了,我们所有应用服务基本都是在云上的,我们通过 Kubernetes + Docker 的方式,去对容器进行部署、管理、编排。
那么我们所对应的基础镜像由 MySQL 的社区版 5.7.21,加上 os Linux 组成基础镜像。其中是通过用 dockfile 的方式来制作 MySQL 的镜像,所以我们整体的一个环境供应是标准化的。
整体容器采用富容器方式部署,一个 pod 一个容器的方式;采用该方式的原因是对迁移入云的存量应用,以及推广新增环境入云的改造几乎没有,对生产存量的 MySQL 侵入性较小。但我们后续也在研究一个 pod 多个容器的方式,尽可能解耦各组件,轻量化镜像以及更贴近 k8s 源生对 pod 的设计理念。
由于数据库这个东西必须要解决两个技术难点,一个是 IP 固定,为什么这么说?因为在传统运维的过程当中,我们 DBA 一般以 IP 视角去做运维管理的,但是在行内 PaaS 平台上所有应用服务器 IP 是不固定的,这个问题对我们产生了比较大的阻碍,因此我们通过自研的 SR-IOV-cni 插件去实现了网络 IP 的分配以及固定,容器网络的建立。
具体怎么实现呢?这是一台宿主机上面用两个物理网卡,然后对接两个物理网卡做虚拟化,虚拟化出 VF,然后对 VF 虚拟网卡做聚合,也就形成了 cbond,cbond 目的是为了虚拟网卡的高可用,同时把 cbond 以及 IP 给到容器内部的 namespace,这样容器就有了 IP,而且在当容器故障或者重建的时候,由于他的 networkclaim 是不会丢的,所以 IP 可以固定以及保留的。
我们用 SR-IOV 的一个好处,是因为其性能是最接近物理机,而且时延低,一台万兆的可以虚拟出 63 个 VF,也就是说一台物理机上面可以部署 63 个容器,当然生产上面不太会部署这么多数据库在一台物理机上,这样集中风险也比较大。
第二点数据持久化,因为数据库要入云嘛,数据必须得持久化,这是最基本的条件。那我们是怎么做的呢?我们是通过 k8s 的 volume Hostpath 的方式,把 Node 的文件目映射给 pod,从而实现了数据的持久化。
通过自研 csi 实现了存储本地盘以及外置盘的存储自动划分,以及使数据持久化。具体的实现方式通过 csi 的 controller,在 Node 节点上挂载卷调用 csi agent 在 Node 节点上去划分文件系统,期间与盘机层面以及 IaaS 的信息互相交互是通过自己研发的 StarMGR 脚本实现的。
对于备份优化,这一块我们引入了 S3fs,通过配置 S3fs 可以对接分布式存储,通过映射关系可以将后端 bucket 直接挂载本地文件目录,可以直接使用。容器做了两层映射,对 MySQL 的备份没有侵入性。基本上是通过共享目录的方式给到主从,为什么要这么做?是因为在一台主库进行切换的时候,可能切到备份的库上。一般我们的脚本不会再主库进行备份,因此可能需要额外调整划分存储资源,这样就避免了浪费。另外通过集中式的备份能够大大提升备份管理的效率;以及通过低廉的存储介质能够有效降低备份成本;纠结码技术提升备份技术的高可靠。
在我们的优化过程当中,实际上也看到很多坑。第一,网络流量,这个在推广分布式架构中预想不到的事情,我们在一次版本投产期间,因为一般情况下每套库为了有一台从库作为回退库或者保障库,我们会断开主从。但是由于分布式架构下 MySQL 节点数量多,等到版本投完,我们恢复主从,发现同城园区的一个网络区域应用交易几乎全部延迟,后面查到原因是什么呢,我们恢复同城的时候把一个网络区域的火墙给打趴了,一次性恢复主从,会造成流量的泄洪效应,直接压垮火墙,导致整个网络区域其他应用受波及。采用的解决方案是控制同城主从之间恢复的并发度,会有一个队列实时监控网络流量。
第二,大事务,大事务实际上会影响主库的交易连续性以及主从延时,因此我们现在自行开发了一些大事务的监控,并逐渐走向自动 Kill,但自动 Kill 这个事可能对有些应用程序还是影响比较大的,所以我们也在斟酌,同时我们会制定相应的开发指引,杨老师也说到指引本身没有问题,但是落地很难,所以我们也在考虑引进一些审核。
第三,大表,大表也是在我们版本投产的时候出现的,之前我们关注可能确实比较少,曾经有一个应用两亿的表,它做了 DDL,简直就是跑死人。所以我们的应对策略是会定期去收集一些大表去促进开发制定数据清理,包括 DDL 测试的迁移一样,MySQL 的审核。
这边是后面的一个具体工作思路:
第一,自动化,由于目前还停留在数据库自动切换阶段,后续目标增加数据库与网络、应用层面的联动,实现业务级别的故障自愈。
第二,服务化,现在我们的架构 IaaS 和 PaaS 还是有一定的隔阂,那是通过 IaaS 供应宿主机,我们把这些宿主机加上 PaaS 平台当中作为资源去管理,后续是打通 IaaS 和 PaaS 通过服务的方式去提供数据库服务供应。
第三,弹性。这是上容器一个很迫切的需求,因为在有一些业务量突增,我们是非常需要弹性资源的扩缩,我们目前阶段还是处于需要停机去做扩缩,当然可以减少停机影响去做主从切换来规避,我们目标也是希望能够容器层面实现动态在线扩缩。
第四,多租户。因为我们行也有 SaaS,那 SaaS 和 PaaS 之间我们也没有一定的对接关系,但这是我们后面一个工作方向,进一步研究隔离性更好的虚拟化方案。大家知道 docker 是共享宿主机内核的,它的隔离是不彻底的,所以这块也是我们后续的一个工作方向。
以上就是我跟大家交流的一个近两年我们在 MySQL 上面的实践经验,谢谢大家。
Q & A
Q1:你们的 MySQL 有 1000 多个,每个实例大概有多大?占的空间?数据的存储?
A:四五百 G。
追问:有没有用 MGR?
A:没有,我们现在有一个团队在研究 MGR 这一块,但是生产还不敢冒用新的技术,不过对于新技术带来的效益还是我们关心的。
Q2:MySQL 和 cpeh 之间怎么做到衔接?
A:实际上我们备份文件扔到 ceph 上,之前提到资源浪费的情况,以及远程存储的方式,一个是共享的好处,但是这同样带来了一个问题,流量的问题。这个我们也在前端去设计做了流量控制。
追问:S3fs 是作为什么?
A:做数据转化,用于做前端数据备份至 ceph 的中间转换层。
作者介绍:
顾龚磊,工商银行开源数据库运维牵头人,带领团队管理上千个 MySQL 节点的日常维护。MySQL OCP,参与了开源数据库选型的研究评测和技术论证,主导了监控体系、高可用设计等运维体系建设完善,在金融行业率先开启了基于分布式开源数据库架构承担核心交易的实践,较早启动了数据库容器化研究和规模应用,在系统架构、问题诊断、性能优化等领域具有丰富经验。
原文链接:
https://mp.weixin.qq.com/s/0wTytLeRSTWqbh_NCjqOdA
评论