TiDB 搭建正式集群这事,我前后在测试环境和生产环境来回折腾过好几遍。很多人以为把 TiUP playground 里的节点换成三台服务器就是正式集群,真到部署时会发现,端口规划、目录权限、PD 和 TiKV 的拆分、监控组件是否齐全,随便一个环节都能让你卡到半夜。这篇我按实际落地的顺序过一遍,适合已经跑过 TiDB 单机、想上正式集群的 DBA 或后端工程师参考。
1. 开始部署前,先把“正式集群”的定位想清楚
1.1 正式集群和测试环境到底差在哪
我在刚接触 TiDB 时也走过弯路:本地用tiup playground一键拉起来的集群,无脑三节点,PD、TiKV、TiDB 全挤在一台机器上,功能能跑通,就以为正式集群也不过如此。真正到了正式环境才发现,测试集群和正式集群的差距不是“机器更多”,而是三个完全不同的目标:容错、可观测、可恢复。
正式集群要能容忍单台机器故障,关键组件必须满足多数派存活;要能随时看到每个组件的健康状态和性能瓶颈;出了问题之后还要能快速定位、快速恢复。所以部署方式、目录规划、配置参数、监控告警都要按这个目标来设计,而不是把playground的命令原样放大到 16 台机器上。
标题里写了“正式集群”,我理解核心词是“正式”两个字。这意味着从拓扑设计开始就要考虑:PD 至少要 3 个节点,TiKV 至少要 3 个副本,TiDB 计算层要有冗余,监控和告警组件必须随集群一起部署。这些不是可选项,是正式集群的基本盘。
1.2 硬件和拓扑规划:节点分得越清楚,后面越好维护
按我自己的经验,正式集群第一件要做的事不是装软件,而是把节点角色分清楚。TiDB 集群里主要有四类角色:
- TiDB Server:无状态计算层,负责 SQL 解析、优化、执行,对客户端暴露 4000 端口,相当于 MySQL 服务端。
- PD Server:集群管理组件,负责元数据存储、调度、时间戳分配和全局事务 ID 分配,外部端口是 2379,内部通信端口是 2380。
- TiKV Server:真正的数据存储层,按 Raft 协议保存数据副本,对外端口 20160,内部 Raft 消息端口 20161。
- 监控组件:包括 Prometheus、Grafana、Alertmanager,负责采集指标、展示面板和告警。
这里有一个常见误区:觉得 PD 只是“管元数据”,随便丢一台小机器上就行。实际不是。PD 写的是 etcd,对 IO 和稳定性要求很高,PD 抖动会直接影响整个集群的调度和事务。生产环境里我建议 PD 和 TiKV 分开部署,至少在物理机或云主机层面不要共用同一块云盘。
下面是我常用的一个 6 节点规划示例:
| 节点角色 | 推荐配置 | 备注 |
|---|---|---|
| PD x3 | 4C 8G,SSD 盘 100G | 三节点满足 Raft 多数派,挂掉一台不影响选举 |
| TiKV x3 | 16C 32G,SSD 盘按数据容量规划 | 三副本默认,三节点是最低容错规格 |
| TiDB x2 | 8C 16G,普通 SSD | 无状态,可用 2 台并负载均衡 |
| 监控节点 x1 | 4C 8G,普通盘 200G | 部署 Prometheus、Grafana、Alertmanager |
如果机器实在不够,PD 和 TiKV 短时间共用一台也不是不行,但数据目录和部署目录一定要分开,且不要在一台机器上同时跑两个 PD。因为 PD 的 Raft 选举要求严格,同机多实例会引入虚假的网络分区风险。
1.3 版本选型为什么重要
TiDB 的版本迭代速度很快,社区尝鲜版和长期支持版之间的差距不是“功能多少”,而是线上稳定性。正式集群我只建议选 LTS 版本。我写这篇时常用的是 6.5、7.5、8.1 这几个 LTS 系列。读者在实际安装时可以敲下面命令看当前最新稳定版本:
tiup list tidb版本选定之后,整个部署过程都通过TiUP统一管理。TiUP 是 TiDB 的包管理和集群运维工具,它既能部署集群,也能做后续的升级、扩缩容、配置热更新。正式环境我都是让 TiUP 来做,自己手写 systemd 管理 TiDB 进程这种方案,虽然可玩性高,但维护成本实在太大,不建议你这么做。
2. 环境初始化:正式集群能不能稳,往往藏在这些细节里
2.1 系统参数和字符集设置
TiDB 对操作系统的要求没有某些数据库那么苛刻,但几个内核参数和生产环境必备的高并发调优项,还是需要提前配好。
我在每台部署节点上都会检查并确认下面这些值:
# 关闭 swap 倾向,TiKV 不希望内存被换出 vm.swappiness = 0 # 允许足够多的内存映射区域 vm.max_map_count = 262144 # 文件句柄上限 fs.file-max = 1000000 # TCP 连接队列 net.core.somaxconn = 65535 net.ipv4.tcp_max_syn_backlog = 65535 # 本地端口范围 net.ipv4.ip_local_port_range = 1024 65535修改方式不复杂:放到/etc/sysctl.d/90-tidb.conf,然后执行sysctl --system。
另外,检查主机名和 DNS。集群内部节点之间要用 TCP 通信,主机名解析一旦混乱,TiKV 之间报错会非常难排查。我的习惯是所有节点 hosts 文件里都写上各节点 IP 和对应的短主机名,不要依赖内部 DNS,也不要使用带特殊字符的长主机名。
2.2 文件系统和挂载参数
TiKV 对磁盘 IO 的敏感性很高。正式集群的 TiKV 数据盘强烈建议使用 SSD 或 NVMe,机械盘跑 TiKV 基本是灾难。
创建文件系统时,我推荐的格式是 ext4 或 XFS,挂载参数里加上noatime,nodiratime,减少访问时间更新带来的额外 IO。
举个例子,假设新数据盘是/dev/sdb:
# 如果是全新盘 mkfs.ext4 -F /dev/sdb # 挂载到数据目录 mkdir -p /tidb-data mount -o defaults,noatime,nodiratime /dev/sdb /tidb-data同时在/etc/fstab里写挂载项,避免重启后数据目录悬空。这一步千万不能省,我见过有人部署完正常,重启机器后 TiKV 起不来的情况,最后发现就是数据盘没自动挂载。
还有个容易忽略的点:分区对齐和 IO scheduler。现在的 NVMe SSD 一般不需要调整 IO scheduler,但如果是 SATA SSD,建议把 scheduler 改成 noop 或 none,减少 IO 排队延迟。这个可以在实际部署后通过监控观察再做决定。
2.3 用户、目录和 SSH 的坑
TiUP 默认会创建名为tidb的系统用户,但这个动作依赖 SSH 连接时是否有sudo权限。如果你使用 root 用户执行tiup cluster deploy,部署进程会自己创建tidb用户。如果你使用普通用户执行,则要确保该用户有免密 sudo 权限,否则部署中创建目录、设置属主都会失败。
SSH 方面,建议提前配置好免密登录,至少把从部署机到所有目标机器的免密打通。每次部署都输入密码也可以,但遇到几十个节点的规模时,还是免密效率最高。验证方式:
ssh root@10.0.0.11 "hostname"在每台节点上确认返回正常,再往下走。
3. 编写 topology 文件并执行 TiUP 部署
3.1 一份可落地的示例拓扑
TiUP 部署集群的核心是一个 YAML 格式的topology文件。它描述每个角色分布在哪些机器、安装到哪个目录、数据写到哪个目录。
我这里给出一份适合正式集群的最小拓扑示例,读者根据自己机器 IP 替换即可:
global: user: "tidb" ssh_port: 22 deploy_dir: "/tidb-deploy" data_dir: "/tidb-data" pd_servers: - host: 10.0.0.11 - host: 10.0.0.12 - host: 10.0.0.13 tikv_servers: - host: 10.0.0.14 data_dir: "/tidb-data/tikv" - host: 10.0.0.15 data_dir: "/tidb-data/tikv" - host: 10.0.0.16 data_dir: "/tidb-data/tikv" tidb_servers: - host: 10.0.0.17 - host: 10.0.0.18 monitoring_servers: - host: 10.0.0.19 grafana_servers: - host: 10.0.0.19 alertmanager_servers: - host: 10.0.0.19几个细节说明一下:
global.deploy_dir是程序安装目录,global.data_dir是数据目录。两者默认最好分开,这样升级/重装程序时数据不会被动。- PD、TiKV、TiDB 这几类角色都支持在 YAML 里单独指定各自的机器,也可以单独覆盖
deploy_dir和data_dir。 monitoring_servers、grafana_servers、alertmanager_servers通常放在同一台机器,因为 Prometheus 的抓取端口 9090、Grafana 的网页端口 3000、告警端口 9093 之间没有特殊冲突。- 如果集群规模大,TiDB 和 TiFlash 等组件可以后续再往 YAML 里加,不影响之前的部署。
3.2 部署前检查与正式部署命令
在真正执行部署前,先做一次环境检查:
tiup cluster check ./topology.yaml这个命令会检查 SSH 连通性、磁盘挂载、CPU 架构、端口占用、系统参数等。看到Fail级别的问题要处理完再继续,尤其是“目录权限不可写”“目标端口被占用”“系统参数不符合要求”这几种。
部署命令一句话就能完成:
tiup cluster deploy tidb-prod v7.5.0 ./topology.yaml -i ~/.ssh/id_rsa部署完成后不要急着连接数据库,先用启动命令把整个集群拉起来:
tiup cluster start tidb-prod然后通过 display 命令查看集群状态:
tiup cluster display tidb-prod正常状态应该是所有角色都是Up,也就是说 PD、TiKV、TiDB、Prometheus、Grafana、Alertmanager 都处于运行中。
部署完成后,TiUP 会提示一段“集群已部署完成”的信息,里面包含了tiup cluster的日常运维命令。这段信息值得记下来,后面扩缩容和升级都会用到。
4. 核心配置项与参数调优:先跑通,再优化
4.1 TiDB Server 侧的关键配置
刚部署出来的集群,TiDB Server 默认配置对大多数业务来说能跑,但有几个点我会重点确认。
第一个是SQL 审计文件大小和保留策略。正式环境一般在tidb_servers.config中设置:
tidb_servers: - host: 10.0.0.17 config: log.level: "info" log.file.filename: "/tidb-deploy/log/tidb.log" log.file.max-size: 300 log.file.max-days: 30这样可以让 TiDB 日志按大小滚动,避免单日志文件把磁盘打满。
第二个是连接数限制。默认max_connections对正式业务来说可能不够,但也不要盲目调到几十万。先看业务连接池怎么设置,再决定具体值。通常 10000 以下即可,过大的连接数反而容易把 TiDB Server 的线程资源消耗在上下文切换上。
第三个是内存和并发参数。TiDB 的计算层是无状态的,不要配置每台机器独占所有内存,因为 SQL 的内存使用受mem-quota-query限制,单查询内存溢出会导致 OOM。建议在 Jaeger/Grafana 面板上观察一段时间后再细化。
4.2 TiKV 侧参数:不要过度魔改
TiKV 的参数非常多,新手最容易犯的错是看了一篇调优文章就大面积修改配置。我个人的建议是:正式集群初期保持 TiUP 默认参数,只按业务情况调整几个明确选项。
例如raftstore.sync-log保持默认 true,不要关。关掉同步写日志会让写入性能指标好看很多,但宕机时数据丢失风险显著上升。
TiKV 的 block cache 建议设置一个合理的上限。默认情况下 TiKV 会按机器内存比例自动划分,如果你发现大量热点读请求都打到磁盘,可以适当调大:
tikv_servers: - host: 10.0.0.14 config: storage.block-cache.capacity: "8GB"这个值不能超过机器物理内存的 50%,否则 TiKV 进程和 OS 页缓存会互相挤压。
PD 侧参数更简单。正式环境里,PD 数据量不会像 TiKV 那样暴涨,一般不需要动max-replicas。默认三副本对多数业务是合理选择。
4.3 部署完立刻要做的事:确认监控可用
正式集群不能“裸跑”。TiUP 部署时已经把监控组件装好了,但你要确认几件事:
- Grafana 是否能打开,默认端口是 3000,用户/密码初始通常是
admin/admin。 - Prometheus 的 Target 里是否能看到所有 TiDB、PD、TiKV 节点的
prometheusjob。 - Alertmanager 是否已经配置了接收端。
如果 Grafana 打开一片空白,先检查tiup cluster display中监控节点是否Up,然后检查防火墙是否放行了 3000、9090 端口。防火墙这块是部署后最常见的“玄学故障”,后面单独讲。
5. 集群部署后的健康检查与压测:别急着接业务
5.1 通过 SQL 和命令行确认集群状态
部署完成只是起点,正式接入业务前一定要做一轮完整验证。我常用的检查方式分三步。
第一步,确认 TiDB Server 能不能正常连接:
mysql -h 10.0.0.17 -P 4000 -uroot第二步,在 TiDB 里执行几个关键 SQL,核验集群整体状态:
SELECT VERSION(); SELECT * FROM information_schema.cluster_info;这个查询能看到所有节点的地址、型号、状态。如果缺失某个角色节点,大概率是对应进程没有正常启动。
第三步,用 PD 控制工具查看 store 状态:
tiup ctl pd -u http://10.0.0.11:2379 store输出里每一行是一个 TiKV store,重点看state字段,正常是Up,is_alive是 true。如果有Offline或Disconnected,说明 TiKV 节点可能宕机或网络不通。
5.2 用 sysbench 做一个基础压测
正式集群不压一下,不放心。我常用 sysbench 做点查基准测试,不是为了追求极限性能,而是验证集群能稳定承担读写流量。
先准备一个简单的 sysbench 配置文件:
mysql-host=10.0.0.17 mysql-port=4000 mysql-user=root mysql-password= mysql-db=sbtest time=120 threads=32 report-interval=10 db-driver=mysql导入压测数据:
sysbench --config-file=config oltp_point_select --tables=8 --table-size=100000 prepare执行压测:
sysbench --config-file=config oltp_point_select --threads=32 --time=120 run注意,压测前先看集群监控里的 CPU、内存、磁盘 IO,如果压测过程中出现TiKV timeout,不要急着调参,先确认是不是磁盘 IO 已经打满,或者单机压力过大。很多“配置问题”其实都是硬件选型问题。
6. 常见问题与排查实录:这些坑我基本都踩过
6.1 端口不通和防火墙问题
TiDB 集群内部组件之间通信端口很多,下面这个表是我每次部署前都会核对的口径:
| 组件 | 端口 | 用途 |
|---|---|---|
| TiDB Server | 4000 | MySQL 客户端协议 |
| TiDB Server | 10080 | TiDB 状态端口 |
| PD | 2379 | 客户端访问 PD |
| PD | 2380 | PD 节点间 Raft 通信 |
| TiKV | 20160 | 客户端/ TiDB 访问 TiKV |
| TiKV | 20161 | TiKV 节点间 Raft 通信 |
| Prometheus | 9090 | 指标抓取端口 |
| Grafana | 3000 | Web 面板 |
| Alertmanager | 9093 | 告警组件端口 |
防火墙如果没放行,表现通常是“连接超时”。我见过最典型的是 TiKV 区域网络开了 20160,但忘了 20161,节点间 Raft 消息无法通信,集群状态时好时坏。排查命令:
telnet 10.0.0.14 20161或者用nc -vz。如果是云主机,还要检查安全组策略,不只看 OS 防火墙。
6.2 PD 频繁选举或 timeout
现象:TiDB 日志里不断出现pd timeout,TiDB 的连接偶发报错,Grafana 面板里 PD 的region heartbeat延迟很高。
常见原因有两个。第一个是机器时钟没有同步。Raft 和 etcd 对时钟敏感,时钟跳变会导致选举异常。正式环境每台节点都配置 NTP 或者 chrony 做时间同步:
chronyc sources -v确认^*开头的上游源是同步状态。第二个是磁盘 IO 慢,导致 PD 写盘延迟高,心跳和选举超时。这种情况需要把 PD 数据盘迁移到 SSD 上,不能继续用机械盘。
6.3 TiKV 启动不了,报目录权限或磁盘空间不足
TiUP 部署的 TiKV 默认会占用一部分预留空间,防止磁盘写满后出现问题。如果数据盘空间不够,会报类似no space left on device,有时候 df 看还有残留空间,但 TiKV 会因为预留空间设置启动失败。
应对方法:
- 检查数据盘挂载是否正常,
df -h和mount一起看。 - 检查
/tidb-data/tikv目录属主是否为tidb用户。 - 如果确认是预留空间问题,可以在拓扑配置里调整:
tikv_servers: - host: 10.0.0.14 config: storage.reserve-space: "5GB"重新tiup cluster reload tidb-prod即可。这个值默认是自适应计算,但磁盘本身不大时,手动设置更可控。
6.4 监控面板看不到数据
部署完成后 Grafana 打开但数据是空的,不要先怀疑 TiUP 部署失败。优先看 Prometheus 的 Targets 页面:
curl http://10.0.0.19:9090/api/v1/targets如果 Target 里某些节点是Down,多半是网络和端口问题;如果 Target 全是Up,但图表曲线依然为空,检查 Prometheus 采集周期是否正常,以及 Grafana 数据源是否指向了正确的 Prometheus 地址。
这个问题的排查思路是:从下往上逐层看,先看节点进程、再看抓取目标、最后看面板数据源。很多人一上来就改面板配置,往往方向就错了。
7. 个人建议:把这些习惯刻进日常运维里
正式集群部署完成只是开始,后面还有升级、扩容、缩容、备份恢复这些长期工作。我的个人习惯是,部署完成后立刻做三件事:第一,把topology.yaml归档到 Git,任何拓扑调整都走提交记录,否则半年后没人记得改过什么;第二,开启 Grafana 的关键告警,至少要覆盖 PD 健康状态、TiKV 空间还剩多少、集群整体 QPS 是否有明显下降,不要等到业务反馈才发现节点挂了;第三,每季度做一次tiup cluster upgrade前的备份和演练,升级本身不复杂,但没验证过的备份恢复,永远等于没有备份。
还有一个使用上很难察觉但很实用的点:TiUP 集群的配置文件修改,不要手贱直接去服务器上改/tidb-deploy下的 YAML,所有配置变更都改本地的topology.yaml,再通过tiup cluster reload下发生效。这样集群实际运行配置和你的版本库文件才能保持一致,避免“线上配置漂移”这种非常难查的问题。
TiDB 搭建正式集群是个熟能生巧的过程,跑通一次之后再搭第二套、第三套会快很多。等到你哪天能从监控面板上快速判断出是磁盘慢还是网络抖,是 PD 调度瓶颈还是 SQL 本身写得差,这套集群才算真正玩明白了。