外观
TiKV Server 组件
角色定位
TiKV Server 是 TiDB 分布式数据库的分布式存储引擎,负责数据的持久化存储、复制和高可用。它是 TiDB 架构中的存储层核心组件,为上层 TiDB Server 提供可靠的数据存储服务。
核心功能
- 分布式键值存储:提供基于范围的分布式键值存储服务
- 数据复制:基于 Raft 协议实现数据多副本复制
- 强一致性保证:通过 Raft 协议保证数据的线性一致性
- 自动分片:数据自动划分为 Region,支持水平扩展
- 分布式事务:支持乐观锁和悲观锁,实现 ACID 分布式事务
- 热点数据处理:自动检测和处理热点数据
- 数据压缩:支持多种压缩算法,降低存储成本
架构特点
- 基于 RocksDB:使用 RocksDB 作为本地存储引擎
- Raft 一致性:基于 Raft 协议实现数据复制和一致性
- 水平扩展:支持通过增加节点线性扩展存储容量和性能
- 高可用性:数据多副本存储,自动故障转移
- 跨 AZ/Region 部署:支持跨可用区或跨地域部署,提高容灾能力
- 云原生设计:支持容器化部署和 Kubernetes 管理
架构设计
内部模块
TiKV Server 内部包含多个核心模块,协同工作提供分布式存储服务:
1. 网络层
- 功能:处理节点间通信和客户端请求
- 协议支持:gRPC 协议,高效的跨语言通信
- 连接管理:管理与其他 TiKV 节点、PD 节点和 TiDB 节点的连接
- 负载均衡:客户端请求的负载均衡
2. Raft 层
- 功能:实现 Raft 共识算法,保证数据一致性
- Raft 组管理:管理多个 Region 的 Raft 组
- 日志复制:负责 Raft 日志的复制和提交
- Leader 选举:处理 Raft 组的 Leader 选举
- 成员变更:支持 Raft 组成员的动态变更
3. 存储引擎层
- 功能:负责数据的本地存储和管理
- RocksDB 封装:对 RocksDB 进行封装,提供高效的键值存储
- 多列族支持:支持多个列族,优化不同类型数据的存储
- 数据压缩:支持多种压缩算法(如 Snappy、LZ4、Zlib 等)
- 事务支持:支持乐观锁和悲观锁事务
4. Coprocessor 层
- 功能:在存储层执行部分计算,减少网络传输
- 下推计算:支持谓词下推、聚合下推等计算下推
- 分布式执行:支持并行执行多个 Coprocessor 任务
- 减少网络开销:将计算靠近数据,减少数据传输量
5. 事务层
- 功能:实现分布式事务
- 乐观事务:基于 Percolator 模型的乐观锁事务
- 悲观事务:支持悲观锁,适合高冲突场景
- 两阶段提交:实现分布式事务提交
- MVCC 支持:多版本并发控制,支持快照读
6. Region 管理
- 功能:管理数据分片(Region)
- Region 拆分:当 Region 大小超过阈值时自动拆分
- Region 合并:合并相邻的小 Region,减少元数据开销
- Region 迁移:根据 PD 的调度指令迁移 Region
- 热点处理:自动检测和处理热点 Region
数据组织方式
1. Key-Value 模型
TiKV 采用键值对存储模型,所有数据都以键值对的形式存储:
- Key:全局唯一的字节串,按照字典序排序
- Value:对应的数据字节串
- Version:每个 Key 可以有多个版本,支持 MVCC
2. Region 机制
- 定义:TiKV 将数据按照 Key 范围划分为多个 Region
- 默认大小:96MB(可配置)
- Raft 组:每个 Region 的副本组成一个 Raft 组
- 副本数量:默认 3 个副本,可配置
- Leader 节点:每个 Raft 组有一个 Leader 节点,处理所有读写请求
- Follower 节点:其他节点为 Follower,负责复制日志和参与投票
3. 数据分布
- Range 分片:数据按照 Key 范围自动分配到不同 Region
- 副本分布:副本分布在不同节点,优先跨 AZ/Region 分布
- 数据均衡:PD 自动调度 Region,平衡节点负载
- 热点调度:PD 自动识别热点 Region,将其分散到不同节点
Raft 协议实现
1. Raft 基本概念
- Leader:每个 Raft 组有一个 Leader,处理所有客户端请求
- Follower:接收 Leader 的日志复制,参与 Leader 选举
- Candidate:在 Leader 选举过程中,竞选 Leader 的节点
- Term:选举周期,每个 Term 最多有一个 Leader
- Log:Raft 日志,记录所有修改操作
- Commit:日志被多数节点复制后,标记为已提交
2. Raft 核心流程
- Leader 选举:当 Follower 超过选举超时时间未收到 Leader 的心跳,会转变为 Candidate 发起选举
- 日志复制:Leader 接收客户端请求,将操作记录为日志条目,复制到所有 Follower
- 日志提交:当日志被多数节点复制后,Leader 提交日志并应用到状态机
- 成员变更:支持动态添加或移除节点,保证系统可用性
3. TiKV 对 Raft 的优化
- 并行 Raft 组:每个 Region 对应一个 Raft 组,多个 Raft 组并行运行
- Pipeline 复制:支持日志的流水线复制,提高复制效率
- 批量提交:将多个小日志条目批量提交,减少网络往返
- Pre-vote:在发起选举前进行预投票,减少不必要的选举
- Learner 角色:支持 Learner 角色,用于节点加入或跨数据中心复制
部署与配置
部署方式
1. 使用 TiUP 部署
部署命令:
bash
# 编辑拓扑文件
vi topology.yaml
# 部署集群
tiup cluster deploy <cluster-name> <tidb-version> topology.yaml --user root -p
# 启动集群
tiup cluster start <cluster-name>拓扑文件示例:
yaml
global:
user: "tidb"
ssh_port: 22
deploy_dir: "/tidb-deploy"
data_dir: "/tidb-data"
server_configs:
tikv:
log.level: "info"
storage.scheduler: "rocksdb"
tikv_servers:
- host: 10.0.0.3
port: 20160
status_port: 20180
- host: 10.0.0.4
port: 20160
status_port: 20180
- host: 10.0.0.5
port: 20160
status_port: 201802. 使用 TiDB Operator 部署
YAML 配置示例:
yaml
apiVersion: pingcap.com/v1alpha1
kind: TidbCluster
metadata:
name: basic
spec:
version: v7.5.0
tikv:
replicas: 3
template:
spec:
containers:
- name: tikv
resources:
requests:
cpu: 4
memory: 8Gi
limits:
cpu: 8
memory: 16Gi
storageClassName: local-storage
volumeMounts:
- name: tikv-data
mountPath: /var/lib/tikv
storage:
volumeClaimTemplates:
- metadata:
name: tikv-data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Ti
storageClassName: local-storage核心配置参数
1. 基本配置
| 参数 | 默认值 | 说明 |
|---|---|---|
server.port | 20160 | TiKV Server 监听端口 |
server.status-port | 20180 | 状态端口,用于监控和管理 |
server.advertise-address | 空 | 对外暴露的地址 |
server.labels | {} | 节点标签,用于调度 |
2. 存储配置
| 参数 | 默认值 | 说明 |
|---|---|---|
storage.data-dir | "./data" | 数据存储目录 |
storage.scheduler | "rocksdb" | 存储引擎调度器 |
storage.engine | "rocksdb" | 存储引擎类型 |
storage.rocksdb.db-options | RocksDB 数据库级配置 | |
storage.rocksdb.defaultcf-options | 默认列族配置 | |
storage.rocksdb.writecf-options | 写列族配置 | |
storage.rocksdb.lockcf-options | 锁列族配置 | |
storage.rocksdb.raftcf-options | Raft 日志列族配置 |
3. Raft 配置
| 参数 | 默认值 | 说明 |
|---|---|---|
raft.raft-entry-max-size | 8388608 | Raft 日志条目的最大大小(字节) |
raft.max-inflight-msgs | 256 | 每个 Raft 组的最大未处理消息数 |
raft.store-pool-size | 2 | Raft 存储线程池大小 |
raft.apply-pool-size | 2 | Raft 应用线程池大小 |
raft.raft-base-tick-interval | "2s" | Raft 基本 tick 间隔 |
raft.raft-election-timeout | "10s" | Raft 选举超时时间 |
4. 事务配置
| 参数 | 默认值 | 说明 |
|---|---|---|
storage.txn.local-latches | 20480 | 本地锁数量 |
storage.txn.pessimistic-txn | true | 是否启用悲观事务 |
storage.txn.enable-async-commit | true | 是否启用异步提交 |
storage.txn.enable-1pc | true | 是否启用一阶段提交优化 |
配置文件管理
- 配置文件路径:默认位于
$DEPLOY_DIR/conf/tikv.toml - 动态配置:部分配置支持运行时修改,无需重启服务
- 配置重载:使用
tiup cluster reload [cluster-name] -R tikv命令重载配置 - 在线修改:通过 PD 或 TiDB Operator 在线修改配置
监控与运维
监控指标
TiKV Server 提供了丰富的监控指标,可通过 Prometheus 收集和 Grafana 可视化:
1. Raft 指标
tikv_raft_logs_total:Raft 日志总数tikv_raft_logs_committed_total:已提交的 Raft 日志数tikv_raft_leader_count:当前 Leader 数量tikv_raft_leader_transfer_total:Leader 转移次数tikv_raft_propose_failed_total:Raft 提议失败次数
2. 存储指标
tikv_storage_size_bytes:存储总大小tikv_storage_available_bytes:可用存储大小tikv_rocksdb_bytes_written_total:RocksDB 写入字节数tikv_rocksdb_bytes_read_total:RocksDB 读取字节数tikv_rocksdb_sst_read_bytes_total:SST 文件读取字节数
3. 事务指标
tikv_txn_commit_total:提交的事务总数tikv_txn_rollback_total:回滚的事务总数tikv_txn_lock_keys_total:锁定的键总数tikv_txn_conflict_total:事务冲突总数tikv_txn_pessimistic_lock_total:悲观锁总数
4. 网络指标
tikv_network_bytes_sent_total:发送的字节数tikv_network_bytes_received_total:接收的字节数tikv_network_connections_total:当前连接数tikv_network_incoming_connections_total:传入连接总数
日志分析
1. 日志格式
文本格式:
[2024/01/20 10:00:00.123 +08:00] [INFO] [server.rs:1234] ["server is running"] [addr="0.0.0.0:20160"] [status_addr="0.0.0.0:20180"] [version="v7.5.0"]JSON 格式:
json
{
"level": "info",
"ts": "2024-01-20T10:00:00.123+08:00",
"caller": "server.rs:1234",
"msg": "server is running",
"addr": "0.0.0.0:20160",
"status_addr": "0.0.0.0:20180",
"version": "v7.5.0"
}2. 关键日志分析
- Raft 日志:记录 Raft 组的状态变化、Leader 选举、日志复制等
- Region 日志:记录 Region 的拆分、合并、迁移等操作
- 事务日志:记录事务的提交、回滚、冲突等
- 错误日志:记录系统错误和异常情况
常见运维操作
1. 查看 TiKV Server 状态
bash
# 使用 tiup 查看状态
tiup cluster display <cluster-name> | grep tikv
# 查看进程状态
ps -ef | grep tikv-server
# 查看端口监听
netstat -tlnp | grep 201602. 重启 TiKV Server
bash
# 重启单个 TiKV Server 节点
tiup cluster restart <cluster-name> -R tikv[0]
# 重启所有 TiKV Server 节点
tiup cluster restart <cluster-name> -R tikv3. 升级 TiKV Server
bash
# 升级集群所有组件
tiup cluster upgrade <cluster-name> <new-version>
# 仅升级 TiKV Server 组件
tiup cluster upgrade <cluster-name> <new-version> -R tikv4. 扩容 TiKV Server
bash
# 编辑拓扑文件,添加新节点
vi topology.yaml
# 扩容集群
tiup cluster scale-out <cluster-name> topology.yaml5. 缩容 TiKV Server
bash
# 编辑缩容配置文件
vi scale-in.yaml
# 缩容集群
tiup cluster scale-in <cluster-name> -N <tikv-node-ip>:20160性能优化
存储优化
1. RocksDB 优化
调整内存配置:
tomlstorage.rocksdb.defaultcf-options = [ "write_buffer_size = 134217728", "max_write_buffer_number = 4", "max_background_jobs = 8" ]选择合适的压缩算法:
tomlstorage.rocksdb.defaultcf-options = [ "compression_per_level = [no, no, lz4, lz4, zstd, zstd, zstd]" ]优化写入性能:
tomlstorage.rocksdb.defaultcf-options = [ "level0_file_num_compaction_trigger = 10", "level0_slowdown_writes_trigger = 20", "level0_stop_writes_trigger = 30" ]
2. Region 优化
调整 Region 大小:
tomlraftstore.region-max-size = "96MB" raftstore.region-split-check-diff = "16MB"优化 Region 分裂策略:
tomlraftstore.split-region-check-enabled = true raftstore.split-scan-limit = 10000
Raft 优化
调整 Raft 线程池大小:
tomlraft.store-pool-size = 4 raft.apply-pool-size = 4优化 Raft 日志复制:
tomlraft.max-inflight-msgs = 1024 raft.raft-entry-max-size = 67108864
事务优化
选择合适的事务模式:
toml# 高冲突场景使用悲观事务 storage.txn.pessimistic-txn = true # 低冲突场景使用乐观事务 storage.txn.pessimistic-txn = false启用异步提交:
tomlstorage.txn.enable-async-commit = true storage.txn.enable-1pc = true
高可用性与容灾
高可用性设计
- 多副本存储:默认 3 副本,可配置为 5 副本
- Raft 共识算法:保证数据的强一致性和高可用性
- 自动故障转移:节点故障时自动选举新 Leader,RTO < 30 秒
- 跨 AZ 部署:将副本分布在不同可用区,提高容灾能力
容灾部署
- 跨 Region 部署:将副本分布在不同地域,实现异地容灾
- 备份恢复:定期备份数据,确保数据可恢复
- TiCDC 同步:实时同步数据到其他集群,实现灾备
故障恢复
- 节点故障:自动检测并处理节点故障,Raft 组重新选举 Leader
- 网络分区:处理网络分区情况,保证数据一致性
- 数据损坏:通过副本恢复损坏的数据
- 集群恢复:支持从备份恢复整个集群
常见问题与排查
1. Raft 组 Leader 频繁切换
现象:Raft 组的 Leader 频繁切换,影响性能
排查步骤:
- 检查网络延迟:确认节点间网络延迟是否正常
- 检查系统负载:确认节点 CPU、内存、磁盘 I/O 是否过高
- 检查 Raft 配置:确认 Raft 选举超时时间是否合适
- 检查日志:查看 TiKV 日志中关于 Raft 选举的记录
解决方案:
- 优化网络环境,降低节点间延迟
- 增加节点资源,降低系统负载
- 调整 Raft 选举超时时间:toml
raft.raft-election-timeout = "15s" - 检查并修复硬件故障
2. 存储性能下降
现象:TiKV 存储性能下降,写入或读取延迟增加
排查步骤:
- 检查磁盘 I/O:确认磁盘 I/O 是否饱和
- 检查 RocksDB 状态:使用
tikv-ctl查看 RocksDB 状态 - 检查 Region 分布:确认是否存在热点 Region
- 检查系统资源:确认 CPU、内存使用情况
解决方案:
- 使用更高速的存储设备(如 NVMe SSD)
- 优化 RocksDB 配置,调整缓存大小和压缩算法
- 处理热点 Region,如调整数据分布、优化应用设计
- 增加 TiKV 节点,分散负载
3. Region 数量过多
现象:集群中 Region 数量过多,影响元数据管理
排查步骤:
- 查看 Region 数量:使用
pd-ctl查看集群 Region 数量 - 检查 Region 大小:确认是否有大量小 Region
- 检查分裂策略:确认 Region 分裂配置是否合适
解决方案:
- 调整 Region 大小阈值,减少 Region 数量:toml
raftstore.region-max-size = "128MB" - 启用 Region 合并,合并小 Region:toml
raftstore.enable-cross-table-merge = true - 优化表结构设计,减少热点数据
4. 事务冲突频繁
现象:事务冲突频繁,重试次数增加
排查步骤:
- 检查事务模式:确认当前使用的是乐观事务还是悲观事务
- 分析业务逻辑:确认是否存在高冲突的业务场景
- 检查事务大小:确认是否有过大的事务
解决方案:
- 切换到悲观事务模式:toml
storage.txn.pessimistic-txn = true - 优化业务逻辑,减少事务冲突
- 缩小事务范围,减少锁定资源
- 增加事务重试次数:toml
storage.txn.retry-limit = 20
5. 节点无法加入集群
现象:新节点无法加入集群,或现有节点无法正常启动
排查步骤:
- 检查网络连接:确认节点间网络是否正常
- 检查节点配置:确认节点配置是否正确
- 检查数据目录:确认数据目录权限和空间是否正常
- 检查日志:查看 TiKV 日志中的错误信息
解决方案:
- 修复网络连接问题
- 调整节点配置,确保与集群一致
- 检查并修复数据目录权限问题
- 根据日志错误信息进行针对性修复
最佳实践
1. 部署建议
- 生产环境:建议部署至少 3 个 TiKV Server 节点,实现高可用性
- 资源配置:每个 TiKV Server 节点建议配置 8C 16GB 内存起,配备高速 SSD
- 存储选择:使用 NVMe SSD 获得最佳性能,使用普通 SSD 获得平衡的性能和成本
- 网络配置:确保节点间网络延迟低,带宽充足
- 跨 AZ 部署:将副本分布在不同可用区,提高容灾能力
2. 配置建议
- Region 大小:根据业务场景调整,一般建议 64MB-128MB
- Raft 副本数:生产环境建议 3 副本,对容灾要求高的场景建议 5 副本
- 压缩算法:根据数据特点选择,建议默认使用 LZ4 或 ZSTD
- 事务模式:根据业务冲突情况选择乐观事务或悲观事务
- 日志级别:生产环境建议设置为 "info",避免过多日志影响性能
3. 监控建议
- 核心指标:监控 Raft 状态、存储使用、事务性能、系统资源等
- 告警配置:设置合理的告警阈值,及时发现问题
- 日志管理:定期清理日志,避免磁盘空间不足
- 定期巡检:定期检查集群状态,发现并解决潜在问题
4. 维护建议
- 定期备份:使用 BR 工具定期备份数据
- 定期升级:及时升级到最新版本,获取性能优化和 bug 修复
- 定期检查:使用
tikv-ctl和pd-ctl定期检查集群状态 - 文档记录:记录集群配置和维护操作,便于后续管理
常见问题(FAQ)
Q1: TiKV Server 与 RocksDB 是什么关系?
A1: TiKV Server 使用 RocksDB 作为本地存储引擎,将分布式键值对存储在本地 RocksDB 中。TiKV 对 RocksDB 进行了封装和优化,提供了分布式存储服务。
Q2: TiKV Server 如何实现强一致性?
A2: TiKV Server 基于 Raft 共识算法实现强一致性。每个 Region 的副本组成一个 Raft 组,只有当多数副本确认收到并提交日志后,才会将修改应用到状态机,从而保证数据的线性一致性。
Q3: TiKV Server 支持哪些压缩算法?
A3: TiKV Server 支持多种压缩算法,包括:
- No:不压缩
- Snappy:高压缩速度,中等压缩率
- LZ4:更高的压缩速度,适合高写入场景
- Zlib:高压缩率,较低的压缩速度
- ZSTD:平衡的压缩速度和压缩率,适合大多数场景
Q4: 如何查看 TiKV Server 的版本?
A4: 可以通过以下方式查看 TiKV Server 版本:
- 使用 tiup:bash
tiup cluster display <cluster-name> | grep Version - 查看日志:TiKV 启动日志中包含版本信息
- 使用 tikv-ctl:bash
tikv-ctl version
Q5: TiKV Server 如何处理热点数据?
A5: TiKV Server 处理热点数据的机制包括:
- 自动热点调度:PD 自动识别热点 Region,并将其分散到不同节点
- 热点数据打散:支持将热点数据打散存储
- 分区表:应用层可以使用分区表,将数据分散到不同分区
- 主键设计:建议使用分布式主键,如 UUID 或雪花算法,避免热点
Q6: TiKV Server 支持多大的存储容量?
A6: TiKV Server 支持 PB 级存储容量:
- 单个 TiKV 节点的存储容量取决于磁盘大小
- 集群总容量 = 节点数 × 单节点存储容量 × (副本数 - 1) / 副本数
- 已在生产环境中验证支持数 PB 级存储
Q7: 如何扩展 TiKV Server 集群?
A7: 扩展 TiKV Server 集群的步骤:
- 准备新的服务器节点,安装必要的依赖
- 编辑拓扑文件,添加新的 TiKV Server 节点配置
- 使用 TiUP 或 TiDB Operator 扩容集群
- PD 自动调度 Region 到新节点,平衡负载
- 监控新节点的性能和状态
Q8: TiKV Server 与其他分布式存储系统有什么区别?
A8: TiKV Server 与其他分布式存储系统的主要区别:
- Raft 一致性:基于 Raft 协议实现强一致性
- MySQL 兼容:与 TiDB Server 配合,提供 MySQL 兼容的分布式数据库
- 分布式事务:完整支持 ACID 分布式事务
- 云原生设计:原生支持 Kubernetes 部署和管理
- HTAP 支持:与 TiFlash 配合,支持 HTAP 混合负载
Q9: TiKV Server 如何实现分布式事务?
A9: TiKV Server 基于 Percolator 模型实现分布式事务:
- 支持乐观锁和悲观锁两种事务模式
- 使用二阶段提交(2PC)实现分布式事务提交
- 支持多版本并发控制(MVCC)
- 支持异步提交和一阶段提交优化,提高性能
Q10: TiKV Server 的性能如何?
A10: TiKV Server 的性能表现优异:
- 单节点写入性能可达 10 万 TPS
- 随着节点增加,性能线性扩展
- 点查延迟低,适合高频点查询场景
- 支持高并发读写,适合各种业务场景
- 通过优化配置,可以进一步提升性能
