今天我就给大家讲一下我们这边做的数据库运维的自动化平台,他是怎么样子的。首先我会给大家简单介绍一下我们做平台的背景,以及平台的一些技术架构,以及针对我们DBA和开发的需求的全套解决方案。
首先是背景,我们为什么要做RDS,在做RDS之前其实我们也有一套自己的自动化系统,可是我们有了这套自动化系统我们发现有了之后我们DBA还是很忙,每天忙于工单处理,大表DDL,集群搭建,扩容,数据迁移等等。这些东西不能说没有价值,但是对于DBA来说,每一次的重复操作,都会让这个价值指数级下降,并且不能带来成长。所以我们对这些需求做了一个简单的分析。
首先第一个,工单审核,大表DDL,数据权限,都是与数据相关的需求,我们看另一部分,集群扩容,数据迁移,故障转移是与数据库相关的。所以我们这边有一个理念我们一定要让数据相关的全部让他们自助化,让开发去做,而不是让我们DBA去做,而跟DBA相关的全部让他自动化。这就是我们现在的理念。
接下来我们面临一个问题就是改造原系统还是重建一个。老系统很符合一个传统运维系统的“特点”:运维开发自己搭服务器,自己上线,自己维护。这会带来一系列问题,比如自己维护的成本很高,还有就是因为这一套与线上业务应用完全不同,所以无法享用业务成熟的组件以及各种自动化服务。所以我们改变了以前的思路,我们以前自己搭的系统全部废掉,全部用线上的系统,我们从整个系统维护搭建以及我们使用的组件全是线上一模一样的一套,甚至包括我们数据库这些东西,全部托管到我们DBA来,还有对服务器这块交给业务运维他们去管,他们更专业,管得肯定也更好。还有就是原来系统面向DBA的,就是我让你DBA工作稍微不再繁琐,自动化工具,你去点一下做完了,现在我们的理念是面向开发,什么叫面向开发呢?就是我们希望开发与我们DBA的整个交互,靠这个系统来交互,你不要老找我说这说那,你就跟我系统打交道好了,有什么错我们系统会告诉你,告诉你怎么去做,让DBA完全从我们整个平台的日常需求里面脱离出来,这就是我们整个的设计理念。
接下来说说我们的基础架构:
因为我们说了,我们要跟线上业务一样,所以我们前面有了一层slb,做均衡负载的。然后是RDS主体部分,主要由RDS主程序和、动态配置管理中心Lion,数据迁移工具Puma和数据访问层中间件zebra组成,其中zebra中间件是一个基于jdbc的数据库动态链接池。
数据库则是MHA+MySQL的架构。最后有一个轻量级的jobCenter,主要用于执行系统级的命令。
最后是一个Job Center,因为我们DBA需要跟资源打交道,会去做一些资源维护,你需要操作系统级别的权限,我们要实现他,其实我们当时有三种方案,第一个我们在自己的管理服务器之上搭一个服务提供API,你来调度,但这就回到我们以前的老路上,你需要去维护这服务,成本很高。第二个就是我们在我们自己的机器上,去装这些脚本,或者给他一些操作系统级命令他自己去执行,这里面又有一个问题,这样装了之后,我们自己的服务器和线上应用服务器就不一样,当他不一样之后你就无法让业务运维进行统一化管理了,所以我们也抛弃了。我们就选了第三种方案,把我们的命令写在这个MySQL里面,我们专门的管理机去取这个命令去执行,而且这层特别薄,薄到几乎无需维护,这样就跟线上业务一模一样,而且还可以进行水平扩展,所以整个系统下来全部可以水平扩展。
然后我们还有一个无状态任务流中心:
这个主要分为process和task。每个process由多个task组成,每个task可以分成多个并发的子task,每个子task我们都会尽量做成幂等。
整个流程由start开始,并由流程中心的doNext控制,最后的每个任务进入到一个任务队列中,最后jobcenter会取出任务,并fork出新进程具体执行相关任务,并进行回调。为了支持jobcenter的分布式扩展,我们用mysql的任务队列做了一个很轻量级的互斥锁来达到多任务中心的互斥功能。主要是我们给每个task一个初始状态UNDO,然后task center拿到任务后会回去update这个任务,并将UNDO作为条件,然后得到MySQL的匹配行数返回值,如果为1则执行,否则放弃,给其它task center执行。
RDS系统实现了DBA的一键集群搭建,扩容/缩容,备份还原,流量控制,动态迁库/拆库,以及单表拆分等功能。我们主要来看看动态数据迁移。
动态迁库/拆库在可靠性和自动化程度相较之前都有了一个很大的提升。而动态迁库/拆库主要分为四个步骤:1.种子数据的迁移;2.增量数据迁移;3.账号权限迁移;4.数据源切换。而增量数据迁移和数据源切换是关键点。其中增量数据迁移我们支持中间机(搭建MySQL中间机,通过配置过滤规则进行数据同步)和puma两种方式,因为各有优缺点(前者快但繁琐且只能有一个源,而后者虽然稍慢,但是支持多源同目标)。
在切换数据源时,我们采用:校验权限→锁表→校验数据一致性→切换动态数据源→kill被阻塞query→renametable...→resetslave这样一个流程来保证整个流程的安全可靠。其中对于锁表,我们必须在一个事务中进行lock tables,数据一致性校验我们采用官方的checksum算法来check每张表的最后1000条数据(1000是我们的一个经验值),然后针对迁移过程中被阻塞的sql,我们采用直接kill的方式来让业务报错重试,以避免数据的不一致。
而对于单表的自动分库分表,我们采用:配置分表规则→根据规则dump数据→配置增量同步任务→业务开启双写→关闭老表写入这样几步来实现单表的动态拆分。
针对开发人员,我们提供了一个SqlEditor的模块来支持。这个模块集查询,修改、权限配置和数据模糊于一身。它相对于以前的临时权限方案主要有这样几个优点: