mysql 分式部署,MySQL 到底能不能放到 Docker 里跑?

前言node

前几月常常看到有 MySQL 到底能不能放到 Docker 里跑的各类讨论。这样作是错的!这样作是对的!说错的理由也说了一大堆,说对的思想也很明确。你们都有道理。可是我本人以为这样的讨论落地意义不大。由于对与错仍是要实践来得出的。web

因此同程旅游也很早开始了 MySQL 的 Docker 化实践,到目前已经有超一千多个 MySQL 实例在 Docker 平台安全稳定地跑着,DB 运维能力发生了质的提升(DBA 不再用担忧删库跑路了)。算法

固然这样是否是能够证实以前的讨论结论——是对的。我想也不必定,由于咱们还只是一只在学飞行的小鸟,还要更多的学习,因此咱们特将咱们在 MySQL 的 Docker 化上的实践分享给你们。数据库

背景介绍后端

同程旅游早期的数据库都以 MSSQL 为主,这个产品有个特色就是 UI 操做很棒。可是批量和自动化管理很难作,人力的工做不少。后来逐渐替换为 MySQL 后也是按照传统的运维方式管理。致使大部分的工做须要人肉运维。安全

固然像咱们早期使用过的 MSSQL 也是有优势的:就是单机性能比较好,在当年那个资源不够的年代里咱们常能够在高可用的实例上运行多个库。这种状况下物理机数量与实例数量仍是比较可控的,相对数量比较少,人肉运维彻底能够应对。服务器

可是 MSSQL 的缺陷也不少,好比作水平拆分比较困难,致使数据库成为系统中较大的一个瓶颈。但在咱们使用 MySQL+ 中间件(咱们作这个中间件也是下了很多心思的,之后能够分享一下)作水平拆分后就开始解决了这个瓶颈。网络

水平拆分的引入也带来了一个小缺点,就是会形成数据库实例数量大幅上升。举个例子咱们作 1024 分片的话通常是作 32 个 node,一主一从是必须的(大部分状况是一主两从),那么至少 64 个实例,再加上应急扩展和备份用的节点那就更多了(中间件的开发者更但愿是 1024 片就是 1024 个实例)。架构

一次上线作一个 32node 分片扩展从库,两个 DBA 足足花了 4 个小时。另外,若是作单机单实例那确定更不行了,别的不说,成本也会是个大问题,且物理机的资源也未能较大化利用。何况由于 MySQL 单体的性能没优点因此分片居多因此大部分状况下并非每一个库都能跑满整个物理机的。即便有部分能跑满整机资源的库,它的多节点备份,环境一至性和运维动做统一等问题也会让 DBA 一头糟,忙碌又容易出错的工做实际上是无心义的。运维

有了单机多实例运行 MySQL 实例的需求。单机多实例要思考的主要问题就是若是进行资源隔离和限制,实现方案有不少,怎么选?KVM,Docker,Cgroups 是目前的能够实现隔离主流方案。

KVM 对一个 DB 的隔离来讲过重了,性能影响太大,在生产环境用不合适。这是由于 MySQL 运行的就是个进程并且对 IO 要求比较高,因此 KVM 不知足要求 (虽然优化之后 IO 能有点提高)。

cgroups 比较轻,虽然隔离性不是很高,但对于咱们的 MySQL 多实例隔离来讲是彻底够用了(Docker 的资源限制用的就是 cgroups)。可是咱们还想针对每一个 MySQL 实例运行额外的管理进程 (好比监控等等)。用 cgroups 实现起来会比较复杂,而且咱们还想让实例管理和物理机区分开,那 cgroups 也放弃。

至于 Docker,那就很不错了,那些裸用 cgroups 的麻烦它都给搞定了。而且有 API 能够提供支持,开发成本低。并且咱们能够基于 Docker 镜像来作部署自动化,那么环境的一至性也可轻松解决。因此最终咱们选择了 Docker 做为云平台的资源隔离方案 (固然过程当中也作了不少性能、稳定性等的适配工做,这里就不赘述了)。

下面两个图能够形象展现这款产品带来的革命性意义:

MySQL 到底能不能放到 Docker 里跑?

固然要能称之为云,那么平台最基本的要求就是具有资源计算、资源调度功能,且资源分配无需人工参与。对用户来说,拿到的应该是直接可用的资源,而且天生自带高可用、自动备份、监控告警、慢日志分析等功能,无需用户关心资源背后的事情。其次才是各类平常的 DBA 运维操做需求服务化输出。下面咱们就来说讲咱们这个平台是如何一步步实现的。

平台实现过程

站在巨人的肩膀上

我一直认为评价一款数据库的优劣,不能只评价数据库自己。咱们要综合它的周边生态是否健全,好比:高可用方案、备份方案、平常维护难度、人才储备等等。固然对于一个云平台也同样,因此咱们进行了短平快的试错工做,将平台分为多期版本开发。第一个版本的开发周期比较短,主要用来试验,因此咱们要尽量运用已有的开源产品来实现咱们的需求,或者对已有开源产品进行二次开发之后实现定制化的需求。如下是咱们当时用到的部分开源产品和技术。

MySQL 到底能不能放到 Docker 里跑?

下面选几个产品简单说一下咱们经过它实现什么功能:

Percona:咱们的备份、慢日志分析、过载保护等功能都是基于 pt-tools 工具包来实现的。

Prometheus:性能优越且功能强大的 TSDB,用于实现整个平台实例的监控告警。缺点是没有集群功能,单机性能是个瓶颈 (虽然单机的处理能力已经很强了),因此咱们在业务层面进行了 DB 拆分,实现了分布式存储及扩展。

Consul:分布式的服务发现和配置共享软件,配合 prometheus 实现监控节点注册。

Python:管理 Docker 容器中 MySQL 实例的 agent 以及部分操做脚本。

Docker:承载 MySQL 实例并实现资源隔离和资源限制。

整体架构

MySQL 到底能不能放到 Docker 里跑?

容器调度系统如何选择

容器调度的开源产品主要有 Kubernetes 和 mesos,可是咱们并无选用这两个。主要缘由是咱们内部已经开发了一套基于 Docker 的资源管理、调度的系统,至今稳定运行 2 年多了。这套架构稍做修改是符合需求的。

另外第三方的资源调度系统兼容咱们目前的高可用架构,其余自动化管理有些难度,同时资源分配策略也须要定制化。因此最终仍是选择采用了自研的资源调度管理。适合本身现状的需求才是较好的。固然后面有机会作到计算调度和存储调度分离的状况下咱们可能会转向 Kubernetes 的方案。

工做原理

咱们就拿建立集群来举例吧。当平台发起一个建立集群的任务后,首先会根据集群规模 (一主一从仍是一主多从,或者是分片集群) 肯定要建立的实例数量,而后根据这个需求按照咱们的资源筛选规则 (好比主从不能在同一台机器、内存配置不容许超卖等等),从现有的资源池中匹配出可用资源,而后依次建立主从关系、建立高可用管理、检查集群复制状态、推送集群信息到中间件 (选用了中间件的状况下) 控制中心、最后将以上相关信息都同步到 CMDB。

以上的每个工做都是经过服务端发送消息到 agent,而后由 agent 执行对应的脚本,脚本会返回指定格式的执行结果,这些脚本是由 DBA 开发的。这种方式的优点在于,DBA 比任何人都了解数据库,因此经过这种方式能够有效提高项目开发效率,也能让 DBA 参与到项目当中去。开发只须要写前台逻辑,DBA 负责后端具体执行的指令。若是将来功能有变动或迭代的话,只须要迭代脚本便可,维护量极小。

资源的调度分配原则

通过对同程多年的 DB 运维数据分析获得以下经验:

CPU 较大超卖 3 倍,内存不超卖;

同一机房优先选择资源最空闲的机器;

主从角色不容许在同一台机器上;

如有 VIP 需求的主从端口须要一致,无 VIP 需求直接对接中间件的无故口一致的限制;

分片的集群将节点分布在多台物理机上;

产品分类

MySQL 到底能不能放到 Docker 里跑?

核心功能

MySQL 到底能不能放到 Docker 里跑?

以上是已经上线的部分核心功能,还有不少功能就再也不一一展现。

备份恢复系统

MySQL 到底能不能放到 Docker 里跑?

备份工具咱们是用 percona-xtrabackup。经过流备份的方式将数据备份到远端的备份服务器。备份服务器有多台,分别按照所属机房划分。

咱们提供了手工备份和定时备份来知足不一样场景的需求。多实例备份必定要关注磁盘 IO 和网络,因此咱们的备份策略会限制单个物理机上并行备份的数量,另外单个机房备份任务队列的并行度也有控制,确保并行备份任务始终保持到咱们指定的数量。

假如整个机房并行的是 50 个任务,那么这 50 个当中若是有 5 个提早备份完成,那么会新加入 5 个等待备份的任务进入这个备份队列。咱们后来改造了备份的存储方式,直接将备份流入分式存储。

监控告警系统

MySQL 到底能不能放到 Docker 里跑?

在上线这套云平台前,咱们仍是用传统的 zabbix 来实现监控告警的。zabbix 的功能的确很是强大,可是后端的数据库是个瓶颈,固然能够经过数据库拆分的方式解决。

数据库要监控的指标比较多,若是采集的项目比较多,zabbix 就须要加 proxy,架构愈来愈复杂,再加上和咱们平台对接的成本比较高,对一些复杂的统计类查询 (95 值、预测值等) 性能比较差。

因此咱们选了一款 TSDB——prometheus,这是一款性能极强、极其适合监控系统使用的时序性数据库。prometheus 优势就是单机性能超强。但凡事又有两面性,它的缺点就是不支持集群架构 (不过咱们解决了扩展的问题,下面会讲到)。

prometheus 的使用应该是从一年前就开始的,那时候咱们只是把它做为辅助的监控系统来使用的,随着逐渐熟悉,愈来愈以为这个是容器监控的绝佳解决方案。因此在上云平台的时候就选择了它做为整个平台的监控系统。

监控数据采集

prometheus 是支持 pushgateway 和 pull 的方式。咱们选用了 pull 的方式。由于结构简单,开发成本低的同时还能和咱们的系统完美对接。consul 集群负责注册实例信息和服务信息,好比 MySQL 实例主从对应的服务、Linux 主从对应的服务、容器注册对应的服务。而后 prometheus 经过 consul 上注册的信息来获取监控目标,而后去 pull 监控数据。监控客户端是以 agent 的形式存在,prometheus 经过 HTTP 协议获取 agent 端采集到的数据。

监控指标画图

不得不说 grafana 是监控画图界的扛把子,功能齐全的度量仪表盘和图形编辑器,通过简单配置就能完成各类监控图形的展现。而后咱们打通了云平台和 grafana 的关联,用户在云平台须要查看实例或集群信息,只要点击按钮便可。

MySQL 到底能不能放到 Docker 里跑?

MySQL 到底能不能放到 Docker 里跑?

告警管理

告警管理分为:告警发送、告警接收人管理、告警静默等功能。prometheus 有一个告警发送模块 alertmanager,咱们经过 webhook 的方式让 alertmanager 把告警信息发送到云平台的告警 API,而后在云平台来根据后面的逻辑进行告警内容发送。

alertmanager 推过来的只是实例纬度的告警,因此咱们结合告警平台的实例相关信息,会拼出一个多维信息的告警内容。让 DBA 一看就知道是谁的哪一个集群在什么时间触发了什么等级的什么告警。告警恢复后也会再发一次恢复的通知。

MySQL 到底能不能放到 Docker 里跑?

alertmanager 也是功能强大的工具,支持告警抑制、告警路由策略、发送周期、静默告警等等。有须要能够自行配置。可是这种和平台分离的管理方式不是咱们想要的,因此就想把 alertmanager 对告警信息处理的这部分功能集成到云平台内。

可是官方文档并无说起到 alertmanager 的 API,经过对源码的分析,咱们找到了告警管理相关的 API。而后 alertmanager 的原生 UI 上操做的功能完美移植到了咱们的云平台,同时新增了实例相关集群名称、负责人等更多纬度的信息。

下面是一些操做样例:

当前告警:

MySQL 到底能不能放到 Docker 里跑?

添加告警静默:

MySQL 到底能不能放到 Docker 里跑?

已建立的静默规则:

MySQL 到底能不能放到 Docker 里跑?

慢日志分析系统

MySQL 到底能不能放到 Docker 里跑?

慢日志的收集是经过 pt-query-digest 每小时进行本地分析,分析完成之后将结果写入慢日志存储的数据库来完成的。固然若是用户须要马上查看当前慢日志的状况,也能够在界面点击慢日志分析。分析完成后能够在 UI 界面点击慢日志查看,就能看到该实例的慢日志分析结果。它同时集成了 explain、查看 table status 等功能。

集群管理

集群管理做为该平台的核心功能之一,占据了整个平台 70% 的工做。这些功能就是 DBA 运维中常常须要用到的。咱们的设计思路是以集群为单位,因此同时只能操做一个集群上的实例。这样就不会在一个页面上显示过多无用的信息,看着乱还有可能致使误操做。看了下图中的这些功能就能更明白为何要这么设计了。

MySQL 到底能不能放到 Docker 里跑?

图中只是一部分,还有部分未展现出的功能 (集成中间件、Dashboard、黑屏诊断窗口等),在后版中功能更多。

高可用

高可用方案咱们使用了目前最流行的 MySQL 高可用方案 MHA。MHA 的优缺点就不在这里讲了,有 DBA 同窗的应该都已经很熟悉了。这里我说一下咱们基于同程业务作的调整。

GTID

由于咱们主要使用的 MariaDB,可是 MHA 版本也是不能支持 MariaDB 的 GTID 切换。因此咱们在原有的基础上作了改进,支持了 MariaDB 的 GTID。使用 GTID 之后灵活切换是一个方面,另一个方面是 sync_master_info 和 sync_relay_log_info 就不须要设置成 1 了 (MariaDB 不支持写 table,只能写 file),极大减小了从库复制带来的 IOPS。

切换时调整相关参数

咱们在切换时调整 sync_binlog 和 innodb_flush_log_at_trx_commit 参数,这两个参数是决定数据落盘方式的,默认你们都是设置双 1。这样相对数据最安全,可是 IO 也较高。

云服务的多实例部署会致使一台物理机上既有 master 又有 slave。咱们确定不但愿 slave 产生过高的 IO 影响到同机器的其余 slave(虽然能够 IO 隔离,可是优先下降没必要要 IO 才靠谱)。因此理论上来讲 Master 上面设置双 1,slave 则能够不这样设置。可是切换后原来的 salve 可能会变成了 master。因此咱们默认 slave 非双 1,在 MHA 切换的时候会自动将新 master 的这两个参数设置为 1。

哨兵

咱们在多个点部署了哨兵服务。这个哨兵是一个简单的 API 服务,带上响应的参数能够请求到指定的实例。当 MHA manager 检测到有 Master 没法链接时,会触发 secondary check 机制,带着 master 相关信息请求哨兵节点的 API,根据哨兵节点返回状况,若超过半数没法链接则切换。不然放弃切换。

高可用切换对接 DB 中间件

MySQL 到底能不能放到 Docker 里跑?

DB 中间件和 DB 经过物理 IP 链接,当发生高可用切换时将的 Master IP、Master port 信息推送到 DB 中间件控制中心,DB 中间件拿到配置后马上下发并生效。

实例、库迁移

MySQL 到底能不能放到 Docker 里跑?

迁移功能初衷是为了将平台外的实例或者库迁移到平台里面来,后来随着逐渐使用发现这个功能可挖掘的空间很大,好比能够作平台内库表拆分等需求。实现原理也很简单,用 mydumper 将指定数据备份下来之后,再用 myloader 恢复到指定数据库。

这是一个全量的过程,增量复制用的是用咱们本身开发的一个支持并行复制的工具,这个工具还支持等幂处理,使用更灵活。没有用原生复制的缘由是,假如要将源实例多个库中的一个库迁移到目标实例,那么原生复制就须要对 binlog 作复制过滤,这里面涉及到配置修改,实例重启,因此果断不考虑。

实现过程并无高大上,可是彻底知足需求。固然 mydumper 和 myloader 也有一些问题,咱们也作了小改动之后才实现的。后面咱们计划用流的方式去作数据导出导入 (相似于阿里开源的 datax)。

迁移完成,增量无延迟的状况下,你们会关心迁移先后数据一致性的问题,咱们提供了自研的数据校验工具。实测 300G 的数据校验时间约为 2 至 3 分钟,快慢取决于开多少线程。

屏蔽底层物理资源

对用户来说,平台提供的是一个或一组数据库服务,不须要关系后端的实例是在哪台机器上。资源计算和调度所有由系统的算法进行管理。

提高资源利用率 (CPU、内存)

经过单机多实例,CPU 资源可超卖,有效提升 CPU 资源的利用。内存资源未超卖,可是能够控制到每一个实例的内存使用,确保每一个实例都能有足够的内存。如有剩余内存,则继续分配容器便可,不 OOM 的状况下压榨内存资源。

提高运维效率

效率的提高得益于标准化之后带来的自动化。批量运维的成本很低。之前部署一套分片集群须要花费将近 6 个小时 (不包含对接中间件的 1 到 2 个小时),而如今只须要 5 分钟便可部署完成。而且部署完成之后会将提供一套中间件 +DB 分片集群的服务。

精细化管理

平台上线后有效提升了资源利用率,同时咱们按照 1 库 1 实例的方式,能够有效避免不一样库的压力不均致使相互影响的问题。而且性能监控也能精准到库级别。

结语

以上这些只是一个开始, 后面还有不少功能须要完善,下面是近期策划的一些功能,其中有些已经在后版中开发完成。 随着功能的不断迭代,咱们会打造一个更加完美的私有云平台。

MySQL 到底能不能放到 Docker 里跑?

数据库私有云平台的上线对同程 DB 来讲,意味着一个时代的结束,也意味着一个时代的开始。结束的是传统运维低效、高成本的运维时代,开始的是一个低成本、高效率、高保障的运维时代。咱们相信将来会更美好!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值