微店MySQL自动化运维体系的构建之路

hongkong 7年前
   <p><strong>前言</strong></p>    <p>互联网时代,数据库如何满足敏捷开发、敏捷交付的要求?传统靠DBA人肉执行的方式,但在面对大量业务需求时,DBA手速再快,记忆力再好估计也不能提供好的数据库服务。在介绍自动化运维之前,我们先来了解下如何使用数据库。</p>    <p>数据库的使用方式主要有两种:</p>    <p><strong>应用混合部署(实例):</strong> 有新数据库需求时,很多人都会选择找个实例,建个数据库和帐号提供给业务。</p>    <p>好处是能快速提供数据库服务,这种方式在数据库运维的过程中会出现一些问题:</p>    <ul>     <li> <p>第一,相互影响,个别应用有问题会影响所有数据库;</p> </li>     <li> <p>第二, 应用DB的性能指标(QPS,TPS,RT...)不能获取;</p> </li>     <li> <p>第三,定位问题源困难;</p> </li>     <li> <p>第四,资源使用不合理。</p> </li>    </ul>    <p>为了解决以上问题,最终会有拆库的过程,拆过库的同学都知道,一个拆库动作需要确认很多东西,所花费的时间是非常多的,过程中容易产生故障。</p>    <p><strong>应用独享(实例):</strong> 在虚拟化,微服务深入人心的今天,应用独享实例是数据库给出的解决办法。我们做到的是所有应用独享实例(分库分表的应用如:分成32个库的应用,业务初期阶段会分布在几个实例中,业务确实需要更多资源时再进行自动化拆库扩容)。这种方式需要大量的实例,传统单机单实例的运维体系就需要演变成单机多实例的方式。</p>    <p>由此引出会有一系列问题需要解决:</p>    <ul>     <li> <p>如何快速提供数据库服务?</p> </li>     <li> <p>如何避免数据库资源合理分配?</p> </li>     <li> <p>数据库监控怎么做?</p> </li>     <li> <p>多实例数据库HA怎么做?</p> </li>    </ul>    <p><strong>MySQL的标准化与自动化</strong></p>    <p>我们实现的MySQL自动化运维体系能够解决规模化的痛点,主要包括实例创建、部署、监控、备份、HA切换、迁移、扩容等方面的自动化,所有模块的主发点是要能“自动化”的方式运作,尽量少的人为参与。</p>    <p>一、标准化</p>    <p>数据库上了一定规模后,数据库的各方面都需要标准规范起来,才能接下去做自动化。实例上的标准化我们主要做了以下几点:</p>    <p>1、应用独享实例</p>    <p>2、数据库M<==>S结构,备库不提供业务流量(异地容灾除外)</p>    <p>很多人会选择一主多备,备库提供读流量。这种架构引起的故障挺多的,因为备库一定会存在延时,备库机器也会挂掉。事实上大部分时候流量都在主库是没问题,如果确实主库压力真的太大怎么办,我们应该及时发现问题并作出应对(方法可以是缓存+拆库)。</p>    <p>3、 MySQL标准化(带thread_pool 功能MySQL)</p>    <ul>     <li> <p>数据库版本一致</p> </li>     <li> <p>“相同”的my.cnf(除个别个性参数如server_id,buffer_pool_size等)</p> </li>     <li> <p>文件目录一致</p> </li>    </ul>    <p>二、构建MySQL自动化运维体系</p>    <p>一套好的大规模运维体系DBManage,整体思路是让一切自动化起来,不需要打通机器间的信任关系,避免或减少人为参与。</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/783b22b65e9386ab0390b5aa0343c60c.jpg"></p>    <p>1 <strong>、多实例创建</strong></p>    <p>一台机器上面开启多个不同的端口,运行多个MySQL服务进程,共用MySQL程序,使用不同配置文件,提供服务。</p>    <p>关键点:</p>    <ul>     <li> <p>“相同”的my.cnf(除个别个性参数如server_id,buffer_pool_size等)</p> </li>     <li> <p>数据文件目录标准化</p> </li>     <li> <p>创建实例(1.初始化一个标准的数据库,2.新建实例通过rsync控制速率,通过修改 " my.cnf " 文件新建不同实例,因为mysql_install_db安装新实例会占用过多IO)    </p> </li>    </ul>    <p>2 <strong>、元数据与监控</strong></p>    <p>数据库监控没有采用类似“lepus”的方式,中心控制的方式对于规模化精细化数据库管理冲突。</p>    <p>中心化存在问题:</p>    <ol>     <li> <p>增加实例需要手动录入;</p> </li>     <li> <p>不能获取响应时间RT(tcprstat);</p> </li>     <li> <p>不能获取主机性能数据等等。</p> </li>    </ol>    <p>我们采用自研 db_agent 实现实例的自动发现,各项元数据及性能数据采集,告别人工处理。</p>    <p>每台数据库服务器上运行db_agent;自动发现实例,自动采集实例数据,主机数据,磁盘数据,自动添加监控。db_agent主要实现以下功能。</p>    <ul>     <li> <p>采集实例信息(数据库列表,复制信息,表元数据等等)</p> </li>     <li> <p>心跳更新(每秒更新,因为show slave status的延时是不可靠的)</p> </li>     <li> <p>数据库性能数据( QPS, TPS......)</p> </li>     <li> <p>数据库响应时间RT(tcprstat)</p> </li>     <li> <p>实时慢SQL</p> </li>     <li> <p>主机性能数据(告别Zabbix)</p> </li>    </ul>    <p>3 <strong>、备份</strong></p>    <p>数据库机器部署备份脚本(不区分是否主备机器),告别手动配置。</p>    <ul>     <li> <p>只备份备库(备份前判断脚色)</p> </li>     <li> <p>多实例并发控制(控制速率及时间)</p> </li>     <li> <p>直接写入HDFS 或Server(推荐HDFS存储)</p> </li>    </ul>    <p>4 <strong>、本地执行agent</strong></p>    <p>远程操作DB机器(创建实例,恢复数据库,etc),通过自定义一些消息调起DB机器对应脚本进行操作。</p>    <p>5 <strong>、监控告警</strong></p>    <p>基于db_agent采集数据,性能画图及告警。性能数据写入graphite。</p>    <p>6 <strong>、MySQL高可用</strong></p>    <p>传统的使用MHA做MySQL HA架构是比较通用的方案,主要特点:通过Health Check 监控MySQL集群,应用通过VIP访问MySQL,VIP通过keepalive选主。这里不展开这种方式和一些改进型(Zookeeper +MHA)的痛点,主要讲下多实例下基于Zookeeper是怎么实现MySQL自动化高可用。</p>    <p>改造后的HA架构,跟通常架构的区别在于我们去掉了MySQL集群里的VIP,使用VDDS替代;完全去掉MHA。通过Zookeeper分布式,实现ha_console的高可用。</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/e1f91fc53605deaf4b7d9d8a93e3e72c.jpg"></p>    <p>整个流程是:</p>    <ul>     <li> <p>VDDS(微店分布式数据库) 新建应用配置</p> </li>     <li> <p>ha_agent向Zookeeper注册临时节点,并实时更新实例信息。</p> </li>    </ul>    <p>{</p>    <p>"source_db_role": "slave",</p>    <p>"master_instance": "192.168.1.12_3306",</p>    <p>"repl_status": "ok",</p>    <p>"h_time_delay": 0,</p>    <p>"repl_delay": 0,</p>    <p>"last_change_time": "2016-10-15-01:00:45"</p>    <p>}</p>    <ul>     <li> <p>ha_console根据Zookeeper节点信息构造切换元数据(包括延时,切换对象,复制状态)</p> </li>    </ul>    <p>"192.168.1.11_3306": "{</p>    <p>"source_db_role": "master",</p>    <p>"master_instance": "192.168.1.12_3306",</p>    <p>"repl_status": "ok",</p>    <p>"h_time_delay": 0,</p>    <p>"repl_delay": 0,</p>    <p>"last_change_time": "2016-10-15-01:00:45"</p>    <p>}"</p>    <ul>     <li> <p>ha_console监听alive目录临时节点</p> </li>     <li> <p>alive目录临时节点消失进行切换(判断延时及复制状态,不符合条件不切换),切换VDDS和数据库</p> </li>     <li> <p>切换前记录切换信息(slave:master_log_file: mysql-bin.000007,exec_master_log_pos: 57830。主库恢复后,用来生成日志解析)</p> </li>    </ul>    <p><strong>场景一:</strong> 实例Crash,实例所在的服务器正常运行,ha_agent运行正常。</p>    <p>实例Crash,ha_agent 正常运行,主动删除Zookeeper 临时节点,ha_console 判断数据库角色,是主库走切换流程。原实例起来之后,作为备库运行。</p>    <p><strong>场景二:</strong> 实例所在的主机Crash。(实例和ha_agent同时Crash)</p>    <p>此时,由于ha_agent和实例同时Crash,Zookeeper到ha_agent间的通讯失败。Zookeeper 等待超过租约的时间,ha_console 判断数据库角色,是主库走切换流程。原实例起来之后,作为备库运行。</p>    <p><strong>场景三:</strong> 实例正常,网络异常。</p>    <p>网络异常会发生大量实例掉线或部份异常。大量节点异常:ha_console判断时间范围内异常实例数量,超过阀值不进行切换,同时切换过程:切换脚本会去判断数据库状态,避免误切。(Zookeeper client 连接掉线后,尽管实例及ha_agent正常运行,节点不能重用必须等待超时)</p>    <p><strong>特点:</strong> 完全不需要人工建入,切换元数据自动构建,所有实例自动注册,构造完整的切换元数据,避免了繁锁的配置或配置出错导致不能切换。</p>    <p>7 <strong>、DBTask</strong></p>    <p>通过DBTask 替代人工操作。实现了数据库创建,配置VDDS, 数据库迁移,拆库扩容,恢复等等。整体思路是分解动作,每个脚本干一件事,再串起所有脚本。以数据库迁移为例我们可以分解为各个子任务,串起任务就是一个完整的自动化数据库迁移任务。</p>    <p>数据库迁移:</p>    <ul>     <li> <p>申请可用资源</p> </li>     <li> <p>实例创建</p> </li>     <li> <p>恢复备库A</p> </li>     <li> <p>恢复备库B</p> </li>     <li> <p>配置数据源(VDDS)</p> </li>     <li> <p>切换前检查</p> </li>     <li> <p>切换</p> </li>     <li> <p>清除VDDS配置</p> </li>     <li> <p>关闭老实例</p> </li>    </ul>    <p>数据库资源申请:</p>    <ul>     <li> <p>申请可用资源</p> </li>     <li> <p>实例创建</p> </li>     <li> <p>新建库,MySQL帐号</p> </li>     <li> <p>配置数据源(VDDS)</p> </li>    </ul>    <p>成果及展望</p>    <p>全套自动化运维体系采用:后台由python+shell+go(实时慢SQL解析部分);前端采用laravel+angularjs。 目前单机日常环境运行100+实例,agent的资源占用不多;业务申请数据库资源<1分钟完成;自动化拆库(部份老的合在一起的还是要拆的)等等。</p>    <p>另外随着MySQL自动化运维的深入,我们慢慢地发现这将会演变数据库成私有云平台。对于如何更好地服务业务,如何诊断业务数据库等还需要我们去完善。</p>    <p>参考资料</p>    <ul>     <li> <p>Python Socket通信:</p> <p>https://github.com/chris-piekarski/python-json-socket </p> </li>     <li> <p>Python HDFS</p> <p>https://pypi.python.org/pypi/hdfs/ </p> </li>     <li> <p>响应时间(rt):</p> <p>https://github.com/Lowercases/tcprstat </p> </li>     <li> <p>Python Zookeeper:</p> <p>https://github.com/python-zk/kazoo </p> </li>     <li> <p>go tidb解析SQL 中的表(用来合并分表)</p> <p>https://github.com/pingcap/tidb </p> </li>    </ul>    <p>经平台及作者同意授权转载</p>    <p>来源:微店技术团队 订阅号(ID:weidian_tech)</p>    <p> </p>    <p>来自:http://www.tuicool.com/articles/jUfIviN</p>    <p> </p>