最近有个测试环境需要跑一套TiDB,机器只有一台,不想上云,手头也没有多的物理机。把整个tidb集群单机部署听起来像是“偷懒”的做法,但真正操作起来,从选型到调优再到踩坑,整套流程走一遍,你对TiDB的理解会比我预期中深不少。单机部署不是生产环境的推荐形态,却是开发测试、本地学习、功能验证和压测准备阶段最高效的起手式。这篇文章我按自己的实操路线,把环境准备、部署步骤、配置优化、日常运维和问题排查全记录下来,适合刚接触TiDB,或者想用一台机器快速跑起一套真实分布式集群的朋友参考。
1. 单机部署到底是部署什么:先理清拓扑和选型
1.1 单机上的“集群”长什么样
TiDB 从架构上天然是分布式数据库,一套集群至少涉及三类核心组件:
- TiDB Server:负责 SQL 解析、执行计划生成和分布式算子下推,本身不存数据,是无状态节点。
- TiKV:负责真实数据的持久化存储,按 Region 分片,多副本通过 Raft 协议保持一致。
- PD(Placement Driver):负责整个集群的元信息管理、Region 调度、时间戳分配和全局 ID 分配。
这三类角色各司其职,缺一个就不是完整的集群。单机部署就是把这三类组件全部跑在同一台物理机或虚拟机上,组件之间通过本机网络地址通信。如果有条件,还可以加一个 TiFlash 列存引擎,用于分析型查询场景。
你可能会问:既然都在一台机器上,那和直接装一个 MySQL 有什么区别?区别非常大。单机部署之后,你拿到的是一个完整的分布式数据库,分片、调度、事务、多副本机制全都有效。你可以在本地验证 TiDB 的扩缩容行为、观察 PD 调度日志、体验 TiFlash 的列存加速。这些能力不是单机数据库能模拟的。
1.2 部署方式选型:为什么最终选了 TiUP
TiDB 的部署方式主要有几种:
- 二进制手动部署:需要你自己下载各个组件的二进制包,编写配置文件,用 nohup 或 systemd 拉起进程,还得手动处理组件之间的发现关系。
- Docker Compose / Kubernetes:适合容器化环境,但在一台小机器上直接多容器跑,资源损耗和网络配置成本都不低。
- TiUP:官方的一站式集群管理工具,支持一键安装、部署、启动、扩缩容、升级和销毁集群。
我实测下来,单机部署最推荐的方式就是 TiUP。它的好处在于把集群拓扑定义、组件安装、启动顺序、健康检查这些繁琐的流程自动化了。你不用去记忆 PD 应该先启动还是 TiKV 先启动,不用手动配置 TiKV 之间的心跳地址,TiUP 会按依赖关系处理这些事。
TiUP 下面有两个常用命令:tiup playground和tiup cluster。前者是本地快速测试专用,适合临时拉起一个集群,一条命令搞定;后者适合正式的部署和管理,需要你编写一份topology.yaml拓扑文件,然后通过tiup cluster deploy来部署。单机场景下,如果你只是做功能验证,playground就够了;如果你打算把集群长期跑在这台机器上,甚至做小规模回归测试,建议直接用cluster模式,方便后续维护和升级。
提示:
tiup playground默认会创建一个临时测试集群,退出后数据目录通常会被保留,但进程不会托管,适合“用完就走”的场景。tiup cluster则会把集群写入 TiUP 的管理目录,支持 stop/start/restart 等标准运维操作。
2. 环境准备:先给 TiDB 铺好跑道
2.1 硬件和系统的基本要求
单机部署不需要很高的配置,但也别太小。我建议的最低配如下表:
| 资源项 | 最低要求 | 推荐配置 | 说明 |
|---|---|---|---|
| CPU | 4 核 | 8 核以上 | TiKV 的存储引擎对 CPU 敏感,多核能明显提升压力测试表现 |
| 内存 | 8 GB | 16 GB 以上 | 单机跑 TiDB + PD + TiKV,内存是最容易成为瓶颈的资源 |
| 磁盘 | 100 GB SSD | 300 GB 以上 NVMe SSD | TiKV 底层依赖 RocksDB,随机读写性能直接决定集群上限 |
| 操作系统 | CentOS 7.9 / Ubuntu 22.04 | 同左 | 推荐 64 位 Linux,内核版本 3.10 或以上 |
这里有一个很多人容易忽略的点:磁盘性能和容量同等重要。TiKV 的写入链路要先写 WAL,再刷 SST 文件,如果盘是机械硬盘或老式 SATA SSD,压力一上来延迟立刻飙升。影响范围不只是慢查询,还可能导致 PD 误判节点心跳超时,造成不必要的 Region 迁移。
2.2 内核参数与文件句柄调整
TiDB 在启动时对系统资源有一些隐式要求,环境不达标时,进程可能启动一半就报错。我在第一次部署时就踩过文件句柄不足的坑,具体错误是 “too many open files”。这需要在部署前调整几个参数。
1. 增大文件句柄限制
TiKV 一次会打开大量 SST 文件和 WAL 文件,默认的 1024 文件句柄完全不够。建议在/etc/security/limits.conf中追加:
* soft nofile 1000000 * hard nofile 1000000 * soft nproc 65535 * hard nproc 65535修改后需要重新登录 shell 才能生效,可以通过ulimit -n检查是否变成 1000000。
2. 关闭 swap 或降低 swappiness
TiKV 对延迟极其敏感,一旦发生 swap,内存换页会让处理时间从毫秒级跳到秒级,影响 Raft 心跳上报,严重时节点会被 PD 标记为下线。推荐设置:
echo "vm.swappiness = 0" >> /etc/sysctl.conf sysctl -p3. 调整进程数上限和线程数相关参数
如果使用的是 systemd 启动,所有进程由 TiUP 托管,还需要注意进程可创建的最大线程数。可以在/etc/systemd/system.conf中设置DefaultTasksMax=infinity,否则 TiKV 可能在运行时因为线程创建失败而退出。
4. 检查vm.max_map_count
RocksDB 会创建大量内存映射区,默认的65530可能不够。建议调高到262144:
echo "vm.max_map_count = 262144" >> /etc/sysctl.conf sysctl -p这些参数看起来很底层,但它们决定了集群在高负载下是否稳定。单机部署本来就是“一个进程挂了全挂”的形态,底层的坑尽量提前填掉。
3. TiUP Playground 快速部署实操
3.1 安装 TiUP 与初始化环境
TiUP 的安装脚本托管在官方域名上,直接执行即可。以普通用户身份运行:
curl --proto '=https' --tlsv1.2 -sSf https://tiup-mirrors.pingcap.com/install.sh | sh安装完成后,脚本会提示你加载环境变量。为了后续命令方便,建议直接写入 shell 配置文件:
source ~/.bashrc tiup --versionTiUP 本身是一个组件管理器,它会把所有需要安装的组件,比如tiup playground、tiup cluster、tiup bench等,统一从镜像仓库拉取。首次运行某个组件时会自动下载,这个过程依赖网络,如果源比较慢,可以指定镜像源环境变量,比如:
export TIUP_MIRRORS=https://tiup-mirrors.pingcap.com3.2 一条命令拉起集群
playground最简用法很简单:
tiup playground v8.1.0这条命令会自动下载指定版本的 TiDB、PD、TiKV 和 TiFlash,并按照默认参数在一台机器上启动一个 1 TiDB + 1 PD + 1 TiKV + 1 TiFlash 的集群。启动成功后,终端会输出类似下面的信息:
☁ TiDB Playground Started! TiDB component started on 127.0.0.1:4000 PD component started on 127.0.0.1:2379 TiKV component started on 127.0.0.1:20160 TiFlash component started on 127.0.0.1:3930看到这个输出,集群就已经可以连接了:
mysql -h 127.0.0.1 -P 4000 -u root如果你想自己指定各组件数量,可以用参数控制:
tiup playground v8.1.0 --db 1 --pd 1 --kv 3 --tiflash 1这里--kv 3会在本机启动 3 个 TiKV 实例,监听不同端口。单机跑多个 TiKV 的好处是可以看到真实的 Raft 多副本效果,比如某个 TiKV 进程被 kill 掉后,集群仍然能正常读写。缺点是内存占用会成倍增长,每个 TiKV 默认都要吃不少内存,机器配置不够时别贪多。
3.3 常用部署参数解析
playground的参数非常多,但单机部署时我主要用下面这几个:
| 参数 | 作用 | 使用建议 |
|---|---|---|
--host | 指定外部访问地址 | 如果想通过局域网访问,设为0.0.0.0 |
--db | TiDB 实例数量 | 单机一般 1 个即可 |
--pd | PD 实例数量 | 单机 1 个即可 |
--kv | TiKV 实例数量 | 想模拟多副本可以设 3 个 |
--tiflash | TiFlash 实例数量 | 不需要列存可以设为 0 |
--without-monitor | 不启动监控组件 | 资源紧张时用,省内存 |
--kv.config | TiKV 配置文件路径 | 用于传入自定义配置 |
--db.config | TiDB 配置文件路径 | 用于传入自定义配置 |
举个例子,如果内存只有 8GB,建议这样启动:
tiup playground v8.1.0 --db 1 --pd 1 --kv 1 --tiflash 0 --without-monitor这样只有三个核心进程,内存占用能控制在比较低的水平。监控组件grafana、prometheus虽然很有用,但单机部署测试时经常遇到内存不足,等需要看指标时再手动启动也不迟。
4. 单机部署的性能调优和配置细节
4.1 内存和缓存怎么给才不炸
单机部署最大的限制就是内存。TiDB 集群里,TiKV 的内存占用占总量的比例极高,因为 RocksDB 的 block cache 会缓存热数据块。默认情况下,TiKV 会根据机器总内存自动计算 block cache 大小,但在单机同时跑多个组件时,这个自动计算反而容易造成内存互相抢占,最后触发 OOM。
我的做法是在启动时通过配置文件显式限制 TiKV 的内存。先创建一个配置文件/tmp/tikv-override.toml:
[rocksdb] max-open-files = 256 [rocksdb.defaultcf] block-cache-size = "2GB" [rocksdb.writecf] block-cache-size = "1GB" [rocksdb.lockcf] block-cache-size = "256MB" [server] grpc-concurrency = 4然后通过以下命令使用这份配置:
tiup playground v8.1.0 --kv 1 --tiflash 0 --kv.config /tmp/tikv-override.toml这里有一个很关键的原则:给 TiKV 的内存上限要留出保底余量。比如机器有 16GB,TiKV 的 block cache 总量不要超过 3GB,还要给操作系统 page cache、TiDB Server、PD 留出空间。否则测试过程中会出现“某个进程被 Linux OOM Killer 随机选中”的情况,现象是所有组件一起挂。
TiDB Server 本身也有内存限制,可以在配置文件中设置mem-quota-query,防止大查询把内存打满:
[mem-quota-query] mem-quota-query = "2GB"这个参数会限制单个查询最多使用的内存,超限后 TiDB 会报错而不是直接吃掉整台机器内存。
4.2 磁盘和 IO 相关的配置思路
单机场景下,磁盘不仅是数据目录,也是日志目录、监控数据目录。最好把数据文件和日志文件放在不同磁盘分区,避免日志写满后拖垮数据库。如果没有条件分多块盘,至少要定期清理日志。
TiKV 的 Raft 日志默认和业务数据在同一目录。在测试环境可以考虑关闭 Raft 日志的落盘同步来提升性能,但这绝对不能用于生产。如果大家都知道这是测试环境,可以用如下的方式调整:
[raftstore] sync-log = false这个配置能让写入性能提升明显,但代价是节点宕机时可能丢数据。我只建议在纯功能验证场景使用,跑压测时也建议打开,因为最终结果更贴近真实情况。
除了 Raft 日志,PD 也有一个>echo "net.core.somaxconn = 4096" >> /etc/sysctl.conf echo "net.ipv4.tcp_max_syn_backlog = 4096" >> /etc/sysctl.conf sysctl -p
这些调整不需要重启机器,对已运行进程也不会立刻生效,需要重启数据库进程才能完全应用。所以环境准备一定要做在前面,等集群跑起来再改这些参数,反而要经历一次重启。
5. 部署后的连接验证与日常运维记录
5.1 从 SQL 到 Dashboard 的完整验证链路
集群启动后,第一件事不是急着跑业务,而是把整个集群的健康状态检查一遍。
用 MySQL 客户端连上 TiDB:
mysql -h 127.0.0.1 -P 4000 -u root连上后运行:
SELECT VERSION(); SHOW DATABASES;如果能正常返回,说明 TiDB Server 这一层没问题。接下来检查 PD 和 TiKV 的状态:
SELECT * FROM information_schema.cluster_info;这个系统表会返回所有组件的地址、版本、状态。重点看STATUS列是否为up。如果某个 TiKV 显示down,通常是端口没通或者进程没起来。
然后可以做一个简单的写入验证:
CREATE DATABASE test; USE test; CREATE TABLE t1 (id INT PRIMARY KEY, name VARCHAR(64)); INSERT INTO t1 VALUES (1, 'hello'); SELECT * FROM t1;这套链路走完,说明写入路径、事务提交、Raft 复制逻辑都已经正常工作了。
如果你启动了监控组件,可以用浏览器访问 TiDB Dashboard。playground模式默认会起 Grafana,访问地址会在启动输出中给出。Dashboard 里有非常直观的集群拓扑图、Key 可视化、慢查询分析等功能,强烈建议在部署完成后扫一眼,比纯看日志高效得多。
5.2 单机部署的服务管理:playground 与 cluster 差异
playground拉起的前台进程,一旦终端关闭或者按了 Ctrl+C,整个集群会退出。对临时测试来说这没问题,但如果想长期跑,就要考虑托管问题。
我通常会切换到tiup cluster来管理长期运行的测试集群。需要先写一个topology.yaml:
global: user: "tidb" ssh_port: 22 deploy_dir: "/data/tidb" data_dir: "/data/tidb-data" pd_servers: - host: 127.0.0.1 tidb_servers: - host: 127.0.0.1 tikv_servers: - host: 127.0.0.1然后执行部署命令:
tiup cluster deploy tidb-single v8.1.0 ./topology.yaml tiup cluster start tidb-single这种方式会把集群注册到 TiUP 的管理体系中,后续的restart、upgrade、clean都变得标准化。
注意:这里有一个单机部署的常见误解。有人觉得
playground和cluster都是启动集群,可以混用。实际上playground不写入拓扑,cluster会做严格的状态管理,二者不要混用来管理同一个数据目录,否则会出现端口冲突或者重复注册的问题。
5.3 轻量压测时怎么观察性能
单机部署最大的目的是测试,不是跑生产。在验证稳定后,我会用tiup bench做一次简单压测:
tiup bench tpcc -H 127.0.0.1 -P 4000 -D tpcc --warehouses 4 --threads 16 --time 1m这里 4 个 warehouse 是单机环境的保守选择。如果机器内存不够,可以减少到 1 个,否则 TiKV 的写放大和内存占用会很快把机器拖死。压测过程中,通过 Grafana 查看 QPS、延迟和 CPU 使用率,就能对单机跑出来的性能有一个整体概念。
6. 高频问题排查实录:单机部署常见的坑
6.1 内存不足导致进程被 OOM Killer 杀掉
这个问题我在部署 3 个 TiKV 实例时遇到过。现象是集群运行一段时间后,某几个进程突然消失,用dmesg能看到类似Out of memory: Killed process的记录。
排查思路是先看整体内存分布:
free -h ps aux --sort=-%mem | head -20如果确认 TiKV 占用过高,就直接按上一节的配置方式调小 block cache。如果机器彻底跑不动,先缩减组件数量,把tiflash关掉,只保留一套 TiDB + PD + TiKV。
6.2 TiFlash 启动失败,端口明明没冲突
playground模式默认会启动 TiFlash,但 TiFlash 对 CPU 指令集有要求,某些较老的 CPU 会直接报illegal instruction。遇到这种情况,可以在启动时加--tiflash 0跳过。TiFlash 只是分析加速引擎,对核心事务功能没有影响,测试主流程时完全可以不启动。
如果 CPU 没问题,还要检查磁盘空间。TiFlash 的数据目录有额外占用,而且默认会保持多个版本数据,磁盘不够时启动也会失败。给/tmp和数据目录留足空间即可。
6.3 端口冲突:看起来像集群内部故障
单机部署时所有组件监听本地端口,端口冲突是最高频的问题。常见端口如下:
| 组件 | 默认端口 |
|---|---|
| TiDB | 4000 |
| PD | 2379 |
| TiKV | 20160 |
| TiFlash | 3930 |
| Prometheus | 9090 |
| Grafana | 3000 |
排查方式很简单:
ss -lntp | grep -E '4000|2379|20160'如果有其他程序占用,可以通过参数换成新端口。例如:
tiup playground v8.1.0 --db.port 40016.4 TiKV 报错 “region is unavailable”
这个错误在单机部署中很常见,特别是只启动 1 个 TiKV 时。默认配置下,数据会有多个副本,但副本数不能大于 TiKV 节点数。如果你用默认副本数 3,又只起了 1 个 TiKV,PD 无法满足副本要求,Region 就会一直处于 pending 状态,读写时会报region is unavailable。
解决办法是在启动时配置副本数为 1。可以通过pd.config传入 PD 配置:
[replication] max-replicas = 1或者在启动参数中指定:
tiup playground v8.1.0 --kv 3用 3 个 TiKV 实例来匹配默认副本数。两种方法选哪种,取决于你的测试目标。我的经验是:想验证分布式能力就起 3 个 TiKV;只做 SQL 测试就设 replica 1,资源占用更小。
6.5 连接数过高导致日志刷屏
单机部署时,开发工具、监控采集和业务连接往往都指向同一个 TiDB 实例。默认日志里会记录每条慢查询和连接信息,很容易刷掉整个磁盘。可以调高慢查询阈值:
[log] level = "warn" slow-threshold = 600这样只记录超过 600 毫秒的慢查询,日志量会明显下降。
7. 最后的一些个人建议和扩展方向
单机部署 TiDB 是一个性价比极高的学习路径,因为它把整个集群的各个组件压缩到你面前,你能直观地看到一次写入怎么经过 TiDB、PD、TiKV 的协调,也能快速验证各种配置项对性能的影响。我自己在踩过几次 OOM 和端口冲突的坑之后,摸索出一套比较固定的部署模板:环境参数先调好,TiUP 安装完,playground快速拉起,验证通过后如果需要长期保留,再迁移到cluster模式。
如果你后续想扩展这个集群,思路也很明确:从单机 1 TiKV 扩到 3 TiKV,或者把 TiFlash 重新加回来,只需要改拓扑文件重新执行tiup cluster scale-out。更进一步,如果有多台机器,可以在拓扑里多写几个tikv_servers的 host,就能体验到真正分布式部署的效果。单机部署只是一个起点,但它足够让你在踩坑过程中把 TiDB 的运行机制摸透。