写生产环境TiDB集群,最怕的就是照着文档敲完命令,结果监控面板一片飘红,业务一上线就出幺蛾子。这篇是《(二)TIDB搭建正式集群》,接着之前的环境准备往下走,目标很明确——用TiUP在一批真实的服务器上,把TiDB、PD、TiKV三个组件搭成一套高可用集群,顺便把那些文档里不会写的坑都给你趟一遍。如果你正打算从测试环境往生产环境迁移,或者第一次在公司内网部署TiDB,这篇内容应该能帮你省下不少弯路。
1. 正式集群规划:先想清楚再动手
1.1 为什么正式环境不能用单机“一把梭”
很多朋友是这么入门的:在自己的笔记本或者一台虚拟机上,用TiUP playground命令一键拉起一个TiDB测试实例,跑几个SQL,查一下执行计划,感觉挺简单。等到要上生产了,就想着把playground里的配置搬到一台大内存服务器上,照样跑。这个思路在数据量小、并发低的场景下能凑合,但一旦进入正式业务,问题立刻暴露。
首先是单点故障。TiDB架构里,TiDB无状态,挂了可以再拉;PD是整个集群的大脑,负责存储元数据和调度,PD宕机时间长了,整个集群基本就不可写了;TiKV是实际数据存储节点,一个副本挂了,数据就少了冗余。单机部署意味着这些组件全挤在一台机器上,机器一宕,全盘皆输。
其次是性能隔离完全不存在。TiKV是CPU密集和IO密集型的,PD虽然资源占用不算高,但它是延迟敏感型服务,对时钟和磁盘IO都有要求。TiDB是计算节点,跑复杂查询时CPU会飙高。三者混部在同一个操作系统上,相互干扰,出了问题排查起来也非常痛苦,你根本分不清是哪个组件把资源吃满了。
最后是扩容能力受限。TiDB集群的扩展性在于水平扩展,TiKV不够了加TiKV节点,TiDB压力大了加TiDB节点。单机部署玩不了这套,数据涨上去之后只能原地换机器,而换机器这种事在生产环境里绝对是灾难级别的操作。
所以正式集群的第一步就是:物理隔离组件角色,按职责分配机器。
1.2 节点角色与硬件选型参考
TiDB集群最小的高可用形态是三组件各至少两节点:
- TiDB节点:无状态,前端负载均衡接入,至少2个节点,可以用相对均衡的配置,CPU主频高一点更好。
- PD节点:强一致性要求,节点数建议3个,奇数个方便选主,磁盘IOPS和延迟要求高,数据量不大但写入频繁。
- TiKV节点:数据节点,至少3个节点起步,每个节点副本数为3时,3个TiKV刚好满足一主两从的冗余策略。
硬件选型上,有一个容易犯的错误:以为TiKV最吃内存就把所有钱都花在内存上,结果CPU核数不够,region调度和compaction压力一大,写入就卡住了。TiKV的处理能力跟CPU核数直接挂钩,每张表的数据分布、region分裂合并,都要消耗CPU。建议TiKV节点CPU核数不少于16核,内存不少于64GB,而且在条件允许的情况下,TiKV的数据盘必须用SSD,机械盘在写入放大面前就是灾难。
PD节点因为要做Raft选举和元数据读写,磁盘延迟直接影响集群稳定性。之前踩过一个坑,用了一台共享存储的虚拟机做PD,结果宿主机上其他业务IO一忙,PD的etcd读写延迟飙到几百毫秒,集群leader不断切换,业务端表现为间歇性写入失败。所以PD节点建议用独立物理机或者有IOPS保障的云盘。
TiDB节点对磁盘要求没那么苛刻,但它会缓存表结构信息和一部分统计信息,同时承担复杂的计算任务。建议内存不低于32GB,CPU 8核以上,网络带宽要充足,因为TiDB节点拿数据是从TiKV拉取的。
1.3 端口规划与网络连通性清单
部署之前把端口规划好,省得到时候防火墙这边卡一下,那边挡一下,查半天都不知道问题出在哪。TiDB集群涉及的主要端口:
| 组件 | 默认端口 | 用途 |
|---|---|---|
| TiDB | 4000 | MySQL协议接入端口 |
| TiDB | 10080 | TiDB状态上报端口 |
| PD | 2379 | 客户端连接PD的接口 |
| PD | 2380 | PD集群节点间通信端口 |
| TiKV | 20160 | TiKV gRPC通信端口 |
| TiKV | 20180 | TiKV状态上报端口 |
| Prometheus | 9090 | 监控数据查询端口 |
| Grafana | 3000 | 可视化监控面板端口 |
节点之间的网络要求是内网互通,延迟越低越好。如果在云环境部署,需要保证同VPC内网通信,不要走公网IP互通,一来延迟不可控,二来安全隐患很大。另外所有节点之间的防火墙策略要提前配置好,我之前遇到过集群部署完之后监控面板连不上,排查了半天发现是Prometheus所在节点访问TiKV状态端口被安全组挡住了。
2. 环境初始化与TiUP部署准备
2.1 系统配置与文件系统选择
TiDB官方推荐的Linux发行版是CentOS 7.3+或者RHEL 7.3+,实际测试下来Ubuntu 20.04 LTS和Debian 11也能稳定运行,只是有些初始化脚本里的命令需要微调。内核参数方面,TiUP部署工具会帮我们自动设置大部分参数,但有三个点建议提前手动确认。
文件系统方面,强烈建议数据盘使用ext4或者xfs,不要用zfs或者btrfs,原因很简单——TiKV底层的RocksDB对文件系统有一些特殊的操作要求,比如fallocate、O_DIRECT支持,非主流文件系统容易出现兼容性问题,而咱们部署生产环境,稳定压倒一切,没必要为了尝鲜给自己挖坑。
挂载数据盘的时候有个细节:TiKV的数据目录所在的分区,mount参数建议加上 noatime,关闭文件访问时间更新,可以减少不必要的磁盘写入。另外建议给数据盘单独分区,不要把系统盘和数据盘混在一起,不然系统日志写满磁盘的时候,TiKV直接就被拖死了。
2.2 时钟同步是硬要求
TiDB集群对时钟同步的要求比大多数分布式系统都要严格,原因在于PD和TiKV的Raft协议依赖时间戳来保证事务的一致性。多节点之间如果时钟偏差过大,会出现时间戳回退、事务冲突异常、备份恢复错乱等奇怪问题。
生产环境强烈建议部署NTP或者chrony,所有节点指向同一个时间源。之前部署过一个跨机房的集群,两个机房的NTP源不一样,导致节点间时钟偏差接近1秒,表现出的症状非常诡异——写入偶发失败,报错信息里夹着“timestamp mismatch”之类的字样。当时查了好久,最后逐个节点执行date命令对比,才发现是时钟不同步。
验证方法很简单,在每台服务器上执行:
chronyc sources -v或者用老一点的NTP工具:
ntpdate -q 时间服务器IP用每台机器的时间和基准时间源对比,偏差控制在100ms以内为佳,被测试环境过坑的朋友应该都懂这个数值的含义。
2.3 系统资源限制与性能摸底
TiKV在高并发写入场景下会打开大量文件,建议提前调高open file limit。虽然TiUP部署的时候会自动设置,但有时候受限于systemd服务文件的配置,进程实际能打开的fd数可能不够。
ulimit -n 1048576这个命令在当前shell下生效,如果要永久生效,需要修改/etc/security/limits.conf文件,加上:
* soft nofile 1048576 * hard nofile 1048576性能摸底这一步很多人会跳过,但我觉得值得做。在正式部署TiKV之前,用fio对数据盘做一次简单的读写测试,至少能发现磁盘是否存在隐藏的性能问题。比如有些云主机的数据盘虽然是SSD,但IOPS被限流了,等到上线之后才发现性能不足就晚了。
fio -filename=/data/testfile -direct=1 -iodepth 64 -rw=randwrite -ioengine=libaio -bs=4k -size=1G -numjobs=8 -runtime=30 -group_reporting -name=test重点关注一下4K随机写入的IOPS和平均延迟,如果平均延迟超过10ms,那这块盘跑TiKV会非常吃力,建议要么换盘,要么调整TiKV的写入参数。
3. 中间控制节点与拓扑文件编写
3.1 控制节点部署TiUP
TiUP是TiDB官方提供的包管理器,它的作用有点像Linux下的yum或者apt,但针对的是TiDB生态的各个组件。控制节点单独用一台机器,不部署任何TiDB组件,只装TiUP和相关的运维工具。
curl --proto '=https' --tlsv1.2 -sSf https://tiup-mirrors.pingcap.com/install.sh | sh安装完成后,重新加载环境变量:
source ~/.bashrc然后验证TiUP是否安装成功:
tiup --versionTiUP的组件安装都在用户目录下,默认路径是~/.tiup,如果需要统一管理,可以在安装前设置TIUP_HOME环境变量,指向一个空间充足的分区。之前碰到过一个问题,控制节点的home目录挂载在根分区上,根分区只有20G,装了几套集群的离线镜像之后磁盘告警,差点把控制节点的系统盘撑爆。
3.2 编写拓扑文件的要点
TiUP集群部署的核心是拓扑文件,一个YAML格式的配置文件,描述了集群里各组件部署在哪些节点、各自使用什么端口和目录。这一步是整个部署流程的“图纸”,图纸画歪了,后面全歪。
global: user: "tidb" ssh_port: 22 deploy_dir: "/tidb-deploy" data_dir: "/tidb-data" server_configs: tikv: server.grpc-concurrency: 8 raftstore.apply-max-batch-size: 256 pd_servers: - host: 10.0.1.11 - host: 10.0.1.12 - host: 10.0.1.13 tidb_servers: - host: 10.0.1.21 - host: 10.0.1.22 tikv_servers: - host: 10.0.1.31 - host: 10.0.1.32 - host: 10.0.1.33 - host: 10.0.1.34有几个值得注意的点。第一,global.user字段定义了集群进程的运行用户,TiUP会自动在目标机器上创建这个用户,生产环境建议用独立的用户而不是root。第二,deploy_dir是组件部署目录,data_dir是数据目录,数据目录一定要指向你挂载的独立数据盘。第三,如果某个TiKV节点的数据盘是单独挂载的,可以在该节点下单独指定data_dir,不必所有节点都用全局默认值。
另外需要强调一下TiKV的CPU绑核配置,这是很多生产集群容易忽略的。TiKV默认会使用机器上所有的CPU核心,如果一台机器上还有其他业务进程(比如监控agent、日志采集),就会互相争抢CPU。可以在拓扑文件的server_configs中配置:
tikv: server.grpc-concurrency: 8 raftstore.store-concurrency: 4 storage.block-cache.capacity: "32GB"storage.block-cache.capacity这个参数直接决定了RocksDB的块缓存大小,默认值是总内存的一定比例,如果机器内存大且混部了其他进程,建议显式指定一个合理的值,避免TiKV把内存吃光。
3.3 离线部署的镜像准备
在企业内网环境,服务器通常是不能直接访问外网的。TiUP默认从官方镜像源下载组件,内网环境会安装失败。这时候需要在一台能联网的机器上提前下载好离线镜像包。
tiup mirror clone tidb-community-${version}-linux-amd64 ${version} --all执行完之后会生成一个本地目录,把这个目录整个拷贝到控制节点,然后在控制节点上执行:
tiup mirror set tidb-community-${version}-linux-amd64这样TiUP就会从本地镜像源拉取组件,无需联网。这个离线包里包含了TiDB、TiKV、PD、Prometheus、Grafana等所有组件,一个包全搞定。
离线部署模式在版本选择上要特别小心,最好所有组件的版本保持一致。有些朋友喜欢某几个组件升级到小版本,某几个不升,结果TiDB、TiKV、PD之间的协议版本不兼容,集群跑起来之后TiKV一直报“version mismatch”,这属于自己给自己找麻烦。官方推荐的组合方式是在一个release版本内统一升级。
4. TiUP集群部署实战
4.1 从环境检查到正式部署
拓扑文件写好了,离线镜像准备好了,接下来就是执行部署命令。我习惯分两步走:先检查,再部署。
tiup cluster check ./topology.yaml --user root这个check命令会检查目标机器的CPU、内存、磁盘、时钟同步、系统参数等是否符合要求,如果检查出警告项,建议逐条看完,不要一股脑忽略。有一些warning可以忽略(比如内核版本比官方推荐的低一点点),但有些error必须处理(比如端口被占用、磁盘空间不足)。
检查通过后,执行部署:
tiup cluster deploy tidb-prod ${version} ./topology.yaml --user root -p-p参数表示需要输入root密码来建立SSH信任关系。如果不希望交互式输入密码,也可以用-i /path/to/ssh_key.pem指定SSH私钥。
部署过程会持续几分钟,控制台的输出可以看到每个组件的初始化和启动状态。有几个常见问题在这里提前预警。
- 如果某个节点SSH登录特别慢或者超时,先检查控制节点到该节点的22端口是否通,很多内网环境只开了业务端口,SSH端口被安全策略拦了。
- 如果部署过程中报
permission denied,并且你用的是root用户部署,看一下目标机器的SSH配置是否允许root登录,有些安全要求高的服务器禁止root远程登录,这时候要么改用有sudo权限的普通用户,要么临时开放root登录权限,部署完成后改回来。 - 如果某个组件启动后立即退出,查看组件日志是最直接的排查手段,日志文件在
deploy_dir对应组件的log目录下。
4.2 集群启动与初始化
部署完成后,有一个初始化操作:设置集群的root密码。
tiup cluster enable tidb-prod tiup cluster start tidb-prod注意enable命令在systemd环境下是设置开机自启,如果漏掉这一步,服务器重启之后集群不会自动拉起,这在生产环境是一场事故。建议部署完立即执行。
启动之后可以用tiup cluster display tidb-prod查看集群状态,如果所有节点都是Up状态,说明基本通电了。然后执行初始化密码:
tiup cluster exec tidb-prod --command="tiup cluster change-password"实际上更标准的操作是通过MySQL客户端连接TiDB,用ALTER USER语句修改root密码:
mysql -h 10.0.1.21 -P 4000 -u rootALTER USER 'root'@'%' IDENTIFIED BY 'your-strong-password';这里的密码策略要遵循公司的安全规范,至少包含大小写字母、数字和特殊字符,长度不低于12位。
4.3 验证集群内部的region调度
集群起来之后,别急着接业务,先验证一下数据副本的分布情况。刚部署完的TiKV节点上还没有任何数据,执行下面这条SQL看看集群健康状态:
SELECT * FROM information_schema.cluster_info;用pd-ctl查看region分布情况:
tiup ctl pd -u http://10.0.1.11:2379 store正常情况下每台TiKV节点都应该出现在store列表中,状态是Up。如果某台TiKV节点状态显示Offline或者Disconnect,需要马上看一下该节点的网络和磁盘是不是有问题,别让集群带病上线。
5. 监控告警与Dashboard使用
5.1 Prometheus与Grafana面板配置
TiUP部署集群时会自动带上Prometheus和Grafana,监控数据默认从每个组件的status端口采集。部署完成后打开Grafana,默认端口是3000,初始账号密码是admin/admin,登录后建议第一时间改密码。
Grafana里预置了很多面板,重点要关注这么几个:
- TiDB Overview:集群整体的QPS、延迟、连接数。
- TiKV Details:每个TiKV节点的CPU、内存、磁盘IO、Raft store相关指标。
- PD:PD的leader切换次数、etcd延迟、region数量变化。
其中PD面板里有一个指标特别值得盯——leader change,正常情况下这个数字应该长时间保持稳定,如果频繁变化,说明PD节点不稳定,要么是网络抖动,要么是磁盘延迟高,这是集群健康度的晴雨表。
5.2 告警规则的重要性
很多人在测试环境搭集群从不配告警,但生产环境没有告警监控等于裸奔。TiUP部署的Prometheus自带了一些基础的告警规则,但默认只是记录在Prometheus内部,没有对接告警通道。
推荐的做法是配置Alertmanager,把告警路由到企业内部的钉钉、企业微信或者邮件。TiDB官方提供的告警规则模板覆盖了大部分核心场景,比如TiKV节点down、PD leader切换异常、region副本数不足、磁盘空间不足等。
有一个告警阈值我觉得默认值偏宽松,就是TiKV的磁盘空间使用率,默认可能到80%或者90%才告警。但TiKV在磁盘空间不足时会触发region调度,把数据往其他节点迁移,如果所有节点都到了80%,调度就会非常被动。建议提前在告警规则里把磁盘使用率阈值调到70%,给自己留出处理时间。
6. 常见问题与排查技巧实录
6.1 部署阶段的高频故障
- 问题现象:执行
tiup cluster deploy时长时间卡在某个组件不动。
排查思路:多半是网络问题,控制节点到目标节点的某个端口连接不通。可以用telnet测试对应IP和端口,如果通了再等,如果没通,调整防火墙之后重新部署。
- 问题现象:TiKV启动失败,日志提示
/tidb-data/tikv目录不存在或权限不足。
排查思路:检查拓扑文件里data_dir指向的目录是否存在,以及global.user指定的用户对目录是否有读写权限。TiUP不会自动创建数据目录的挂载点,需要提前建好并把属主改为运行用户。
- 问题现象:集群部署完成,但
tiup cluster display显示某个PD节点Down。
排查思路:第一时间查看PD日志,常见原因是PD集群之间2379端口不通,或者PD节点的etcd数据目录权限不对。PD是集群的命脉,宁可慢一点排查,也不能带病强行启动。
6.2 运行期的隐患和排查心得
集群运行一段时间后,最常遇到的性能问题是TiKV的region分布不均。可以通过Dashboard的Key Visualizer功能查看,如果发现某个节点的数据明显比其他节点多,说明region调度不够积极。这时候需要检查PD的调度参数,特别是region-schedule-limit和leader-schedule-limit,如果这两个值过低,调度就会被卡住。
另一个容易被忽略的问题是多集群共用一套监控组件。如果公司在同一个网段部署了多套TiDB集群,每一套都用默认的端口配置,监控数据会互相覆盖,面板上看到的指标张冠李戴。建议每套集群的Prometheus和Grafana都使用不同的端口,或者在Prometheus的采集配置里严格区分job名称。
6.3 安全加固的几点补充
生产环境的集群需要做一些基本的安全加固:
- TiDB的4000端口不对公网开放,只允许业务应用的IP访问。
- PD的2379端口是内部管理端口,绝对不要暴露给外部,否则任何能访问到这个端口的人都可以用pd-ctl操作集群,包括下线节点这种危险操作。
- Grafana和Prometheus端口建议通过反向代理加一层认证,而不是直接裸奔在内网里。
- 定期备份PD的元数据,虽然PD本身有三副本,但如果整个PD集群损坏,恢复的复杂度远高于TiKV数据恢复。
关于安全这块,我得特意偏离一下那些不当联想,强调一点:TiDB本身的权限体系和MySQL兼容,生产环境务必遵循最小权限原则,为不同业务创建独立账号,只授予必要的库表权限。不要什么应用都拿root去连,出了问题连审计追踪都做不了。
7. 扩容与后续演进建议
7.1 TiKV节点扩容操作
集群的数据量增长到一定程度,三个TiKV节点扛不住的时候,扩容是必然的操作。TiUP的扩容非常方便:
tiup cluster scale-out tidb-prod ./scale-out-tikv.yaml需要编写一个只包含新增节点的拓扑文件,格式和部署时一样,只是只写TiKV部分。扩容过程会自动把新节点加入集群,PD会自动开始往新节点调度region,整个过程业务不需要停机。
扩容的时候有一点要注意:不要一次性扩容太多节点,比如一次加5个TiKV节点,PD会因为要同时往5个新节点迁移数据而产生巨大的调度压力,反而把线上性能拖垮。建议一次扩2个,等region调度到基本均衡之后再加下一批。
7.2 TiDB组件升级的节奏
TiDB的版本迭代速度比较快,很多团队喜欢跟着升级。我的建议是:小版本升级可以积极一点,通常包含bugfix和安全补丁;大版本升级务必先在测试环境完整验证,特别是业务SQL的兼容性和性能变化。
TiUP的升级操作:
tiup cluster upgrade tidb-prod ${new-version}升级过程中TiUP会逐个节点滚动重启,理论上可以在线完成。但实际生产环境,我还是建议找业务低峰期操作,哪怕TiDB宣称在线升级,也要给自己留足回退的余地。
从我个人的实操体验来说,TiDB集群的搭建并不复杂,真正需要用心的地方在于前期的资源规划和后期的运维监控。很多问题看着是部署不成功,追根究底,都是前面某个细节埋下的雷——比如PD的节点磁盘不行、TiKV的CPU核数不够、节点时钟不同步、监控端口没放开。把这几个基础盘打扎实了,TiDB集群跑起来会非常稳,后续维护的精力也能省下大半。
最后再分享一个小建议:集群搭好之后,找一个业务空闲的窗口,做一次完整的kill -9演练,把TiKV节点强制杀掉一个,看看集群是否会按照预期自动恢复。这个动作花不了多少时间,但能让你在真实的故障来临之前,心里先有个底。别等到生产环境挂了再去验证你的高可用方案,那时候的代价就不是一顿加班能解决的了。