TiDB 集群这种东西大家默认是往多台机器上铺或者直接上云。可实际开发中最尴尬的往往是业务还没到需要集群的规模但我就是要一个跟生产差不多的 TiDB 环境用来跑联调、验证 SQL、测试新版本特性。手头只有一台开发机甚至就是自己的笔记本怎么办我这次要分享的就是tidb集群单机部署的完整思路和实操。简单说就是把 PD、TiDB 计算层、TiKV 存储层这三大件全部装到同一台机器上让它在资源有限的情况下仍然扮演一个完整集群的角色。整个过程不复杂但有很多选择会影响你后面用起来爽不爽用官方音乐播放器一样的东西一键启动还是按生产模式手动编排单机该压多少内存给 TiKV要不要启动监控组件这些都是我在实际部署中被问过无数次的问题。这篇文章适合三类人刚接触 TiDB、想在本地快速搭建一套环境验证功能的开发者需要搭一套类似生产架构的测试环境给团队用的运维朋友以及准备把 TiDB 用在真实项目里、想先单机跑一遍全流程的人。1. 为什么要把集群压在一台机器上——先认识 TiDB 集群的构成与单机场景的定位1.1 集群组件与单机资源矛盾一个标准 TiDB 集群最少需要三类进程配合工作PDPlacement Driver集群的大脑负责元数据管理、时间戳分配、Region 调度决策。没有 PD整个集群就是一片散沙。TiDB Server无状态的计算层负责接收 SQL、做解析和优化、把请求下推给 TiKV最后汇总结果返回给客户端。TiKV有状态的存储层负责真实数据落盘、多副本保持、Region 分裂合并。单机部署时TiKV 往往是资源消耗和稳定性压力的核心。除了这三者你还可以选择部署 TiFlash列存副本用于实时分析、Prometheus Grafana监控、Grafana Dashboard 等辅助组件。单机部署的第一个矛盾点就在这里集群正常工作的前提是分布式协调而分布式协调本身就要求多个角色并存但单机的 CPU、内存、磁盘又是固定的。PD、TiDB Server 其实不重真正吃资源的是 TiKV。每份数据默认要求三副本单机没有真正的多机容错副本却照样要占三份空间这在资源紧张的场景下是最大的浪费来源。1.2 什么时候适合单机集群什么时候别这么干根据我自己的使用经验单机 TiDB 集群最适合以下场景功能验证验证某个 SQL 语法、函数在 TiDB 下的行为是否与 MySQL 一致不需要压测。应用联调后端服务本地开发时连接的就是 TiDB保证连接串、事务行为、字符集等逻辑和线上一致。版本升级评估新版本 TiDB 发布了想在部署到测试集群前先在本地单机环境确认兼容性。学习 TiDB 内部机制查看 Dashboard、观察 PD 调度、体会 Region 分裂单机环境信息量足够且可控。而生产环境、高并发压测、数据可靠性验证这三种场景强烈不建议单机部署。单机部署少了跨机房的网络延迟、磁盘故障隔离、进程异常隔离压测结果不具备参考价值多副本在单机上也没有真正的高可用意义因为整机一挂所有副本都跟着挂。我的建议是单机集群的存在价值是Hook 住生产环境的行为而不是替代生产环境。想清楚这一点后面所有的资源分配和参数调整就有了目标。2. 选型TiUP 是唯一靠谱的入口playground 与 cluster 模式的分工2.1 为什么不建议手工下载二进制来拼装早期 TiDB 部署比较原始大家自己去 GitHub 下载各组件二进制包手动写 Systemd 服务再逐个进程启动。这样做的坏处非常明显组件之间的版本兼容关系需要自己维护PD、TiKV、TiDB Server 的版本稍微不匹配就可能出现各种诡异问题。升级要重复手工操作流程复杂且容易出错。集群拓扑信息端口、目录、配置没有统一管理排查问题时连某个进程到底在读写哪个目录都要查半天。现在官方维护了TiUP它是 TiDB 生态的包管理器可以理解为 TiDB 的 App Store 包管理器的结合体。通过 TiUP 部署集群版本统一、配置文件标准化、运维命令齐全是当前最推荐的入口。2.2 playground 与 cluster 模式怎么选TiUP 提供了两种部署模式我经常被问用哪一个这里给出一张对比表对比项playground 模式cluster 模式定位本地快速体验、开发联调接近生产形态的正式环境部署复杂度一条命令自动完成需要写拓扑文件执行 deploy进程管理前台运行CtrlC 退出后台守护start/stop/restart 可控数据保持CtrlC 后数据保留destroy 时清除数据目录由你自己规划destroy 时同样清除扩缩容支持 scale-out / scale-in支持且更接近生产配置方式监控组件默认可选启动按拓扑文件配置默认可集成简单结论如果你想 5 分钟内起来一个环境就用 playground如果你想模拟生产部署目录、端口、配置、权限用 cluster 模式。我后面的实操会同时覆盖这两种因为很多人第一步从 playground 进入但真正常用的是 cluster 模式。2.3 环境准备核数、内存、磁盘和操作系统要求单机部署虽然简单但不是任何配置都能跑。我的底线配置如下供你参考CPU最低 4 核。CPU 不够时TiKV 的 RocksDB 压缩任务和 SQL 执行会互相抢资源表现为整个集群响应非常慢。内存最低 8GB。内存 8GB 时OS 本身的缓存、TiKV 的 block cache 会互相挤压OOM 风险很高。磁盘建议 SSD可用空间 50GB 以上。TiKV 对随机 IOPS 要求高于顺序带宽机械盘跑起来体验很差。操作系统Linux 优先CentOS 7/8、Ubuntu 20.04 都没问题。macOS 其实也能用 playground 模式但 TiKV 在 macOS 下的性能明显弱我不建议做超过功能验证的事情。另外单机部署前我建议把时钟同步检查一下。很多人在单机环境下忽略时钟但 TiDB 内部依赖 PD 分配的TSO如果时钟跳变可能触发 lease 相关问题。当前机器如果没有 NTP 或 chrony至少确认系统时间和真实时间偏差不大。3. 从一条命令开始的部署实操playground 模式跑起来3.1 安装 TiUP 并初始化组件如果你从来没装过 TiUP先执行curl --proto https --tlsv1.2 -sSf https://tiup-mirrors.pingcap.com/install.sh | sh安装完成后需要把 TiUP 的 bin 目录加到 PATH。脚本运行完会输出提示通常是source ~/.bashrc在 macOS 上可能需要source ~/.zshrc。我遇到过用户全都装完了但是卡在找不到 tiup 命令原因就是没刷新 shell 配置。紧接着初始化 TiUP 自己的组件信息tiup playground v8.1.0 --db 1 --pd 1 --kv 1 --tiflash 0我来拆一下这个命令做了什么v8.1.0指定 TiDB 版本号具体版本可以替换成你需要的。如果你不确定有哪些版本可以用tiup list tidb查。--db 1 --pd 1 --kv 1表示各启动一个 TiDB Server、一个 PD、一个 TiKV。--tiflash 0是明确不启动 TiFlash。单机资源本来就不宽裕TiFlash 默认吃内存很大非必要不开。如果什么都不带默认也会帮我们起 TiDB / PD / TiKV 各一个并在适当时候询问是否打开某个面板。第一次执行时 TiUP 会自动下载对应版本的二进制过程取决于网络情况。下载完成后终端会滚动输出大量启动日志最终你会看到类似这样的提示TiUP Playground is starting ... PD client endpoints: [127.0.0.1:2379] tidb server start at 127.0.0.1:4000看到tidb server start at 127.0.0.1:4000就说明环境已经起来了。3.2 让其他机器也能访问--host 参数与端口规划默认情况下playground 启动的服务全部挂在127.0.0.1上只有本机能连接。如果你的应用跑在同一台机器上这没问题。但如果你想让局域网内的同事也连过来联调必须显式指定监听地址tiup playground v8.1.0 --host 0.0.0.0 --db 1 --pd 1 --kv 1 --tiflash 0这里的关键点是TiDB 对外统一入口是 4000 端口PD 是 2379 端口监控相关组件在 9090/3000 端口。要让别人连接还需要确保防火墙放行对应端口。用--host 0.0.0.0时要注意安全性。开发和内网测试问题不大但如果这台机器暴露在公网千万别这么干至少要在应用层做访问控制。我在早期就犯过懒得关 4000 端口对外权限的错误后来想想都后怕那一台机器上连备份数据都没有。3.3 首次验证连接、Dashboard 与监控登录 MySQL 客户端连接mysql -h127.0.0.1 -P4000 -uroot执行SELECT VERSION();正常会返回类似8.0.11-TiDB-v8.1.0的版本号。注意 TiDB 返回的 MySQL 版本号是兼容层的伪版本不用紧张这是刻意设计的兼容行为。然后在浏览器打开 TiDB Dashboardhttp://127.0.0.1:2379/dashboard初始可以用 root 账号、空密码登录。这里能看到集群的实时状态、Region 数量、慢查询、SQL 诊断等信息。单机环境虽然规模小但 Dashboard 的功能都是完备的这也是我喜欢用它来学习 TiDB 的内部行为的原因。至于 Prometheus 和 Grafanaplayground 默认会帮助你启动。Grafana 通常在http://127.0.0.1:3000账号密码都是admin第一次登录会要求重置。里面的 TiDB 监控面板很详细CPU、内存、磁盘 IO、Raft 状态都能看到。3.4 停止与清理如果你只是临时用一用直接 CtrlC 停止 playground 进程即可。数据默认保留在~/.tiup/data/目录下下次重新启动同一版本时还能继续使用。如果不想保留数据执行tiup playground destroy这条命令会把当前 playground 部署的数据目录清掉。我建议测试完一批数据想彻底干净重来的时候再用 destroy平时 CtrlC 就已经够了。4. 更接近生产的单机部署用 TiUP Cluster 的拓扑文件控制一切4.1 为什么需要拓扑文件playground 模式虽然快但我始终觉得它不够生产味道。比如你没法指定某组件的 data_dir 放在哪个磁盘、没法单独给 TiKV 下配置、没法精确控制每个组件的 systemd 资源限制。这时候就该用tiup cluster模式。所谓拓扑文件就是一个描述集群在哪里部署什么、用哪个端口、目录在哪、参数如何的 YAML 文件。TiUP 根据这个文件完成部署、配置、启停和扩缩容而这一切的基础就是拓扑文件写得好不好。4.2 一份单机拓扑文件的完整写法下面是我常用的一份单机集群拓扑文件注释了我的意图global: user: tidb ssh_port: 22 deploy_dir: /data/deploy/tidb data_dir: /data/tidb-data log_dir: /data/deploy/tidb/log resource_control: memory_limit: 10G pd_servers: - host: 127.0.0.1 name: pd-host-1 tidb_servers: - host: 127.0.0.1 port: 4000 status_port: 10080 tikv_servers: - host: 127.0.0.1 port: 20160 config: raftstore.capacity: 150GB monitoring_servers: - host: 127.0.0.1 grafana_servers: - host: 127.0.0.1我来解释几个容易被忽略的点global.user: TiUP 会通过 SSH 登录到目标机创建该用户后续用这个用户管理所有 TiDB 组件。单机部署时我一般先手动创建好一个tidb用户并确保当前用户能免密 SSH 到本机。如果 SSH 配置不好后续部署会被卡在最开始的地方。resource_control.memory_limit: 这会让对应组件以 systemd 的 MemoryLimit 方式限制内存。在单机环境非常重要尤其是防止 TiKV 把内存吃满把整台机器拖垮。具体数值建议根据总内存来配我后面会展开。tikv_servers.config.raftstore.capacity: 这是 TiKV 能使用的最大存储容量。如果磁盘很大最好按实际评估给一个尺寸否则 TiKV 会按磁盘总量的一定比例做物理预分配和空间预估可能带来不必要的空间占用。写完后保存为single-topo.yaml接着执行部署tiup cluster deploy my-single-cluster v8.1.0 ./single-topo.yaml这里的my-single-cluster是集群名自己取后续所有操作都用这个名字。如果拓扑文件中的组件已经存在TiUP 会提示是否覆盖确认即可。部署完成后再启动tiup cluster start my-single-cluster查看状态tiup cluster display my-single-cluster我每次部署完都会用display确认所有组件都是Up状态然后再去执行连接测试。4.3 单机扩缩容scale-out 与 scale-incluster 模式下扩缩容同样存在只是需要写新的拓扑片段文件。比如我想给单机集群再加一个 TiKV 实例tikv_servers: - host: 127.0.0.1 port: 20161 deploy_dir: /data/deploy/tidb/tikv-20161 data_dir: /data/tidb-data/tikv-20161然后执行tiup cluster scale-out my-single-cluster scale-out-tikv.yaml这步的意义在于即使单机你也模拟了多实例扩容的流程。对于以后操作多机集群流程完全一致是个很好的训练场。不过我要提醒一句单机上跑多个 TiKV 实例性能上并不会变好反而会互相争抢 CPU 和磁盘 IO。你扩的是数量不是性能。降低一个实例tiup cluster scale-in my-single-cluster -N 127.0.0.1:20161注意 scale-in 会触发数据搬迁单机上数据搬迁虽然不会跨网络但也需要时间。如果数据量少很快结束如果数据量大耐心等就好。5. 单机集群的资源调优与稳定性内存、磁盘、时钟这些看不见的坑5.1 内存分配策略与 OOM 排查单机 TiDB 集群里进程主要有 PD几百 MB、TiDB Server几百 MB 到 1GB、TiKV占用大头。TiKV 内部包含多个 RocksDB 实例默认 block cache 会尽量占满可用内存这是它性能好的原因也是单机环境容易 OOM 的根源。我的内存分配策略是总内存 16GB 时给 TiKV 限制在 8GB~10GB给 TiDB Server 限制在 2GB其余留给操作系统和辅助组件。如果总内存只有 8GBTiKV 限制在 5GB 左右TiDB Server 控制在 1.5GB监控组件能不开就不开。在上面的拓扑文件里resource_control.memory_limit就是干这个用的。你可能想精确地只限制 TiKV可以在 TiKV 那一节单独写tikv_servers: - host: 127.0.0.1 resource_control: memory_limit: 8G如果没做限制内存不足时系统 OOM Killer 可能会杀掉 TiKV 进程。TiKV 一旦被 OOMPD 会周期性地发现 Region 没有 Leader因为 TiKV 本身没有副本整个集群会进入短暂不可用状态等进程被 systemd 拉起后才恢复。从表象上看就是一会儿能连一会儿不能连非常让人头疼。判断是否发生了 OOM我一般看系统日志dmesg | grep -i oom也可以用dstat或者free -h观察整体内存情况。我建议在部署完成后立刻跑一个简单的内存测试for i in $(seq 1 100); do mysql -h127.0.0.1 -P4000 -uroot -e SELECT count(*) FROM (SELECT 1 UNION SELECT 2) t1, (SELECT 1 UNION SELECT 2) t2;; done这个测试的意义是让 TiDB 频繁解析和执行 SQL确认内存不会在连续并发下暴涨。当然它不能代替真实压测但足以暴露很多最基础的内存问题。5.2 磁盘性能对 TiKV 的影响与部署目录规划TiKV 的写入性能很大程度上取决于磁盘写入延迟和 fsync 稳定性。单机部署时如果/data和系统盘混在一起系统日志、Docker 镜像、普通文件写入都可能造成 IO 抖动进而放大 TiKV 的 Raft 写入延迟。我的建议是独立磁盘放 TiKV 数据如果机器上有系统盘和数据盘之分务必把 data_dir 指向数据盘。目录层级简单不要嵌套太深也不要放在被自动清理扫描的目录下。预留空间给 OS 和日志留 20%~30% 的空间。磁盘满对 TiKV 来说是灾难TiKV 会进入只读或拒绝写入的状态严重时还会影响 PD 心跳。这里要特别提醒raftstore.capacity。如果磁盘是 500GB但实际暂时用不到一定要在配置里写死config: raftstore.capacity: 150GB否则 TiKV 可能会基于磁盘总容量来预估空间做 Region 调度时不会太积极而且当磁盘剩余空间不足时可能触发较保守的行为。提前声明容量能避免很多后知后觉的麻烦。5.3 时钟同步与系统参数看起来无关其实影响选举单机集群最容易忽略的就是时钟。表面上看只有一台机器不存在时钟同步问题。但 TiDB 集群内的机制是随着时间戳走的如果机器被 VM 管理平台做了挂起/恢复或者系统时间被 NTP 强制拨动就可能出现时间回退。TiKV 的 lease 续约和 PD 的 timestamp 分配都会受影响。所以单机部署之前我建议至少确认一下timedatectl另外文件描述符限制和进程数限制也要调一下。TiKV 在高负载下会打开大量文件默认的 1024 远远不够。把它调到上限ulimit -n 655360如果你用的是 systemd 管理拓扑文件里也可以对组件做LimitNOFILE设置。不过大多数发行版的 TiUP 在安装时已帮你把常用参数调好了这里主要是确认而不是改变策略。网络参数方面建议关闭 IPv6 相关的不必要监听保持监听地址干净单一。我遇到过有人在单机部署时TiDB Server 监听在::而非具体的 IP 上导致某些客户端解析握手异常。用--host 0.0.0.0或者拓扑文件中的host明确指定 IP能减少这种奇怪的兼容性问题。6. 跑起来之后如何验证与排障我建议你必查的几个检查项6.1 初检清单进程、端口、数据写入不管用 playground 还是 cluster 模式部署完成我都会按固定顺序走一遍检查检查进程是否都在ps -ef | grep -E tidb-server|pd-server|tikv-server检查端口监听ss -lntp | grep -E 4000|2379|20160通过 MySQL 客户端连接mysql -h127.0.0.1 -P4000 -uroot -e SELECT 1;创建临时数据库和表写入少量数据CREATE DATABASE smoke_test; USE smoke_test; CREATE TABLE t1 (id INT PRIMARY KEY AUTO_INCREMENT, c1 VARCHAR(100)); INSERT INTO t1 (c1) VALUES (hello), (world); SELECT * FROM t1;如果这一步能顺利通过说明基础链路没问题。否则不建议继续往下深入调试业务逻辑。6.2 一次典型的故障排查链路从连接失败到定位端口/资源占用我挑一个很常见的场景来讲排查思路因为这套路径你在单机 TiDB 集群上迟早会用到。现象应用连不上 4000 端口日志报dial tcp 127.0.0.1:4000: connect: connection refused。第一步确认进程是否存活。ps -ef | grep tidb-server如果进程都没了优先看 TiDB Server 是怎么挂的。可能是被 OOM 杀了也可能是自己 panic。看日志ls ~/.tiup/logs/tidb/ # playground 模式默认日志目录 tail -n 200 ~/.tiup/logs/tidb/*.log第二步如果进程在确认监听地址。ss -lntp | grep 4000如果监听的是127.0.0.1:4000但应用连的是本机某个内网 IP必然失败。解决办法在 playground 模式就是重启时加--host 0.0.0.0cluster 模式则是改拓扑文件里的 host 后reload。第三步看端口是不是被别的进程占了。lsof -i :4000如果显示别的进程占了这个端口而 TiDB Server 又是启动成功的大概率是重启过程中端口释放慢造成的。等几秒后重新确认如果持续占用手工处理冲突进程后再启动。第四步确认防火墙。单机本机连接没问题但局域网其他机器连不上十有八九是防火墙。先临时放行端口做验证firewall-cmd --add-port4000/tcp --add-port2379/tcp --add-port20160/tcp也可以临时直接systemctl stop firewalld验证。确认是防火墙后再按正规方式写入永久规则。第五步回到 Dashboard 看全局状态。打开http://127.0.0.1:2379/dashboard看 PD、TiKV、TiDB 三个角色是否健康。如果 TiKV 显示宕机或频繁心跳超时可能就不是连接层问题而是资源问题。这个排查顺序我用了很久每次都能快速缩小范围。记住一个原则先进程再端口再防火墙再集群状态不要一上来就怀疑 TiDB 本身有 bug。6.3 常用诊断命令与监控指标速查单机排障时下面这些命令我随手会用目的命令查看集群全局状态tiup cluster display cluster-name查看 TiDB 慢查询mysql -h127.0.0.1 -P4000 -uroot -e SELECT * FROM information_schema.slow_query查看 TiKV 有没有 Region 不可用tiup ctl pd -u http://127.0.0.1:2379 region check查看 PD 调度的 Region 数tiup ctl pd -u http://127.0.0.1:2379 store系统内存和 IOvmstat 1/iostat -x 1/free -h单机 CPU 抢占情况top里关注si和wa列软中断高说明网络层压力大IO wait 高说明磁盘跟不上监控指标里我最关注的是 TiKV 的Raft store is busy指标。它出现时通常意味着磁盘 IO 或 CPU 已经到瓶颈单机环境下它还经常是因为多个组件抢同一块磁盘导致。此时真正有效的解决方式不是盲目调大 buffer而是减少同时运行的组件、降副本数、关掉 TiFlash。还有Dashboard 里的Top SQL和Key Visualizer是排查热点问题的好帮手。单机部署时热点问题同样会出现因为 TiDB 计算层和数据层都挤在同一台机器上热点查询会直接放大到整机资源占用上。7. 一些我踩过之后才明白的经验总结最后说几个我自己的体会可能比前面的命令更值钱。第一单机 TiDB 集群最适合的用途是体验一致性不是性能一致性。你的应用在单机上和在生产集群上运行的 SQL 行为、事务行为、错误码基本一致但性能和水平扩展能力完全不具备参考性。所以千万别拿单机的结果去给生产容量做预算我见过有人因为在单机上读写飞快就觉得生产 4 字节 32 副本也能飞快后果相当难看。第二端口规划从一开始就要想好。playground 模式很方便但默认端口和生产常用的端口可能不一样。如果你后面要迁到 cluster 模式或者正式环境建议一开始就用 4000/2379/20160 这套标准端口避免应用层配置文件里反复改端口。第三数据目录就是你唯一的保命符。单机没有多副本高可用一旦数据目录所在的磁盘损坏、或者你手动 destroy 清了数据什么高级副本策略都救不了你。所以我做任何测试前都会先确认这批数据丢了影响大不大该导出的导出该备份的备份。第四别一上来就开 TiFlash。TiFlash 确实能让列存相关的 SQL 变快但它在单机上吃内存和 CPU 都非常可观。没有明确分析类 SQL 需求时关掉它你会发现整个环境稳定性提升一个档次。等需要再说用 TiUP 随时能扩出来。第五把整个部署流程用脚本固化下来。无论是 playground 模式的一串命令还是 cluster 模式的拓扑文件和 deploy/start 流程都值得写成一个简单的 shell 脚本或笔记。这样过两个月你再想搭一个全新环境时不需要重新回忆当时到底用了什么参数。我已经因为临时忘记参数而重试过太多次。TiDB 单机部署不是什么高深技巧但它是很多人的第一扇门。把这扇门走通你后面再看多机部署、K8s 部署、生产调优都会觉得顺理成章。
阅读完成 · 觉得有帮助?