背景介绍
随着互联网的飞速发展,业务量可能在短短的时间内爆发式地增长,对应的数据量可能快速地从几百 GB 涨到几百个 TB,传统的单机数据库提供的服务,在系统的可扩展性、性价比方面已经不再适用。为了应对大数据量下业务服务访问的性能问题,MySQL 数据库常用的分库、分表方案会随着 MySQL Sharding(分片)的增多,业务访问数据库逻辑会越来越复杂。而且对于某些有多维度查询需求的表,需要引入额外的存储或牺牲性能来满足查询需求,这样会使业务逻辑越来越重,不利于产品的快速迭代。
TiDB 的架构
TiDB 作为 PingCAP 旗下开源的分布式数据库产品,具有多副本强一致性的同时能够根据业务需求非常方便的进行弹性伸缩,并且扩缩容期间对上层业务无感知。TiDB 包括三大核心组件:TiDB/TiKV/PD。
TiDB Server:主要负责 SQL 的解析器和优化器,它相当于计算执行层,同时也负责客户端接入和交互。
TiKV Server:是一套分布式的 Key-Value 存储引擎,它承担整个数据库的存储层,数据的水平扩展和多副本高可用特性都是在这一层实现。
PD Server:相当于分布式数据库的大脑,一方面负责收集和维护数据在各个 TiKV 节点的分布情况,另一方面 PD 承担调度器的角色,根据数据分布状况以及各个存储节点的负载来采取合适的调度策略,维持整个系统的平衡与稳定。
上面的这三个组件,每个角色都是一个多节点组成的集群,所以最终 TiDB 的架构看起来是这样的。
由此可见,分布式系统本身的复杂性导致手工部署和运维的成本是比较高的,并且容易出错。传统的自动化部署运维工具如 Puppet / Chef / SaltStack / Ansible 等,由于缺乏状态管理,在节点出现问题时不能及时自动完成故障转移,需要运维人员人工干预。有些则需要写大量的 DSL 甚至与 Shell 脚本一起混合使用,可移植性较差,维护成本比较高。
针对 TiDB 这种复杂的分布式数据库,我们考虑通过对 TiDB 容器化管理,实现以下几个目的:
一、屏蔽底层物理资源
二、提升资源利用率(CPU、内存)
三、提升运维效率
四、精细化管理
因此结合上述需要,我们开发了雷神系统来统一管理和维护 TiDB,其整体架构如下:
从架构图中可以看出此方案是 TiDB 的私有云架构。最下层是容器云,中间一层是开发的容器编排工具,最上面一层针对 TiDB 特性和实际使用中遇到的问题点,进行了针对性开发从而实现了 TiDB 集群实例的统一化管理。下面将逐个介绍各个模块的功能。
容器调度
目前主流的的容器编排系统 Kuberbetes 曾是我们容器调度的首选解决方案。但 TiDB 作为数据库服务需要将数据库存储到本地磁盘,而 Kuberbetes 对 Local Storage 不支持(目前新的版本已经开始支持)。针对 TiDB 的特性和业务需求,我们决定自己实现一套容器编排系统,具体解决以下问题:
- 支持 LocalStorage,解决数据存储问题
- 基于 cpuset-cpus 实现 CPU 资源的随机均衡分配
- 定制化,支持 label,实现特定服务运行在特定宿主机上;宿主机资源限制
- 容器的主动发现和通知,以便将之前未管理的宿主机接入统一管理
- 容器的全生命周期的管理
- 容器异常的修复和通知
雷神 Thor 采用了模块化设计,分为控制模块和代理模块,其整体架构如下:
说明:
- 控制模块包含了 Allocator,Label,Discover,Manage,Customize。Allocator 主要负责宿主机资源的分配;Label 主要用于标签定制;Customize 主要负责定制化需求; Discover 主要负责容器的发现和异常检测;Manage 主要负责整体的调度和分发。
- 代理模块主要负责资源检查和信息收集、接受控制端的命令。
集群管理
集群管理是整套系统的核心模块之一,包含了 TiDB 集群的日常维护操作,实现了 TiDB 初始化、平滑升级、弹性容量管理、监控的整合、集群的维护、节点的维护等功能。虽然 PingCAP 提供了基于 Ansible 的自动部署方案,但是依然需要填写大量的内容和检查相关机器设定来完成部署。通过此系统只需要将需求按照如何格式提交,即可完成整套集群的部署,部署时间从之前 2 个小时,缩减为 2 分钟左右。
数据库管理
数据库管理是日常运维很核心的一块,此模块通过任务完成统计信息更新、过载保护、慢查询分析和 SQL 预警。
1. 统计信息更新
TiDB 虽然会自动更新统计信息,但需要达到固定的变更百分比,因 TiDB 是作为分片库的合并库,数据量高达几十亿,若依赖自身的统计信息维护,将出现因统计信息不准确而触发的慢查询,故针对此种情况,设计和开发统计信息自动更新,除常规设定外,还可设定例外,避免因统计信息更新时影响业务的正常使用。
2. 过载保护
通过对 SQL 的执行时间和内存的使用情况分析,针对不同的集群可以定制不同的过载保护策略,也可以使用统一的过载保护策略;当触发策略时,会将相关信息通过微信的方式通知相关人员。
3. 慢查询分析和 SQL 预警
通过 ELK 构建慢查询分析系统,通过 mysql-sniffer、flume、kafka、spark、hadoop 构建 SQL 预警,通过对趋势的分析和预判,为后续自动化容量管理做数据的积累。
数据同步
我们尝试将 TiDB 作为所有数据的集合库提供复杂查询,分片集群则提供简单查询,同时由于 TiDB 高度兼容 MySQL 的连接协议为满足复杂的业务查询需求,我们基于 PingCAP 的数据同步工具 Syncer 进行了代码重构,开发了 hamal 同步工具,可以自定义库名和表名,同时新增了同步状态监控,如 TPS、延迟等,如果出现异常,会通过微信告警。从 MySQL 将数据实时同步到 TiDB 来确保数据的一致。该实时同步查询系统架构如下所示:
Hamal 是伪装成 mysql 从,从 mysql 主上通过主从复制协议来解析成对应的 sql 语句,并经过过滤、改写等步骤,将最终语句在目标库执行的工具。Hamal 主要包含以下特性:
- position 以及 gtid 模式支持
- 自动切换主从支持(需要提前配置好主从服务列表)
- 多目标库支持(多 tidb-server)
- binlog 心跳支持
- 库、表级别过滤,重写支持(用于分片合库)
- 库表级别额外索引支持
- 拆解字段支持(额外输出选择某几个字段的小表)
- 字段过滤支持
- 智能更新表结构
- 多线程合并小事务后执行,多种分发策略
- 纯文本执行模式支持
Hamal 的内部实现如下:
从架构图中可以看出,通过设定不同的 generators,hamal 支持同步到不同目的库或者其他存储方式。
监控和告警中心
监控对于系统的重要性不言而喻。能否有效的告警直接影响着监控的质量,因此监控的核心是监控数据的采集和有效的告警。监控数据主要有三种系统本身的运行状态,例如 CPU、内存、磁盘、网络的使用情况;各种应用的运行状况,例如数据库、容器等,处理网络上发送过来的数据。通过监控项设定和监控例外,可以灵活的定制监控信息的收集。合理、灵活的监控规则可以帮助更快、更精确的定位异常,通过告警策略和告警例外满足不同的告警需求。监控和告警中心的架构图如下:
其中,监控数据的采集一部分依赖于现有监控系统中的数据,如 zabbix 之类;一部分通过 TiDB 的 API 获取,一部分是开源的收集器,因此导致原始数据存储在不同类型的数据库,通过开发的同步工具,将上述数据同步独立部署的 TiDB 集群,以便后续的数据分析。可视化的实现主要基于 grafana 来完成。告警模块是基于实际的需求,进行开发和实现的,未采用现有的一些开源方案。
总结
在对 TiDB 的使用过程中,我们按照 1 库 1 集群的方式进行服务部署,这种部署方式可以有效避免不同库的压力不均导致相互影响的问题,同时性能监控精准到库级别,而使用了雷神系统后,能够有效的在单台服务器上对各种服务资源进行快速部署,提升资源利用率的同时避免资源争用带来的问题。
系统上线一年以来,已完成公司所有 TiDB 集群从物理机部署到容器化的平稳迁移;管理了数百台机器和数十套 TiDB Cluster,接入应用数百个,承载着几十 T 的数据量,峰值 TPS 数十万;上线前部署一个 TiDB 集群需要花费将近 2 个小时,雷神系统上线后只需要 2 分钟即可部署完成。有效的提升了 DBA 的运维效率和整个 TiDB 服务的可用性。
未来我们将继续深入,从审计和 SQL 分析方面着手,为业务提供更多的效率提升和稳定性保障。