TiKV Multi-Raft 机制深度解析
一、Multi-Raft 架构全景
1. Region 与 Raft Group 关系
2. 核心组件协作
二、Region 管理机制
1. Region 元数据结构
// raftstore/src/store/region.rs
pub struct Region {
pub id: u64, // Region 唯一ID
pub start_key: Vec<u8>, // 起始键
pub end_key: Vec<u8>, // 结束键
pub region_epoch: RegionEpoch, // 版本信息
pub peers: Vec<Peer>, // 副本节点
// ...
}
pub struct RegionEpoch {
pub conf_ver: u64, // 配置版本
pub version: u64, // 数据版本
}
2. Region 分裂过程
三、RaftStore 架构设计
1. RaftStore 核心模块
2. Peer 处理流程
// raftstore/src/store/peer.rs
impl Peer {
fn process_raft_message(&mut self, msg: RaftMessage) {
// 1. 消息路由到对应Region
if msg.get_region_id() != self.region_id() {
return Err("Region mismatch");
}
// 2. 处理Raft消息
match msg.get_message().get_msg_type() {
MessageType::MsgAppend =>
self.handle_append_entries(msg),
MessageType::MsgRequestVote =>
self.handle_vote(msg),
// ...
}
// 3. 处理Ready状态
if self.raft_group.has_ready() {
let ready = self.raft_group.ready();
self.save_ready(&ready);
self.send_messages(ready.messages);
self.apply_committed_entries(ready.committed_entries);
}
}
}
四、多 Raft Group 调度
1. 负载均衡算法
2. Region 迁移过程
// pd/server/schedulers/balance_region.rs
impl BalanceRegionScheduler {
fn schedule(&self, cluster: &mut Cluster) -> Operator {
// 1. 识别过载节点
let overloaded = cluster.find_overloaded_nodes();
// 2. 选择待迁移Region
for node in overloaded {
let region = self.select_region_to_move(node);
// 3. 选择目标节点
let target = self.select_target_node(region.size());
// 4. 创建迁移Operator
return Operator::TransferLeader {
region_id: region.id,
from_store: node.store_id,
to_store: target.store_id,
};
}
}
}
五、分布式事务支持
1. Percolator 事务模型
2. Multi-Raft 事务优化
// storage/txn/commands/prewrite.rs
impl Prewrite {
fn process(&self, snapshot: &Snapshot) -> Result<()> {
// 1. 检查所有Key是否在同一个Region
if keys_in_same_region(&self.mutations) {
// 单Region事务
self.prewrite_single_region();
} else {
// 多Region事务
self.prewrite_multi_regions();
}
}
fn prewrite_multi_regions(&self) {
// 1. 并行发送到不同Region
let futures = self.mutations.group_by_region().map(|(region, mutations)| {
send_prewrite_to_region(region, mutations)
});
// 2. 等待所有响应
let results = futures::join_all(futures).await;
// 3. 检查冲突
for res in results {
if res.is_err() {
// 回滚事务
self.rollback();
break;
}
}
}
}
六、Region 分裂与合并
1. Region 分裂流程
// raftstore/src/coprocessor/split_check.rs
impl SplitChecker {
fn check(&self, region: &Region, engine: &Engine) -> Option<SplitRequest> {
// 1. 检查Region大小
if region.size < self.threshold {
return None;
}
// 2. 选择分裂点
let split_key = self.find_split_key(region);
// 3. 创建分裂请求
Some(SplitRequest {
region_id: region.id,
split_key,
new_region_id: self.alloc_id(),
})
}
}
// raftstore/src/store/peer.rs
impl Peer {
fn handle_admin_command(&mut self, req: AdminRequest) {
match req.get_cmd_type() {
AdminCmdType::Split => {
// 1. 验证分裂请求
if !self.validate_split(req) {
return Err("Invalid split");
}
// 2. 创建新Region
let new_region = self.create_new_region(req.split_key);
// 3. 提交分裂日志
let entry = Entry {
entry_type: EntryType::EntryConfChange,
data: new_region.encode_to_vec(),
};
self.raft_group.propose(vec;
}
}
}
}
2. Region 合并过程
七、故障恢复机制
1. Raft Group 恢复流程
2. PD 调度干预
// pd/server/schedulers/region_health.rs
impl RegionHealthScheduler {
fn handle_heartbeat(&self, report: RegionHeartbeat) {
// 1. 检测异常Region
if report.leader_is_none() {
self.handle_no_leader(report.region_id);
}
if report.pending_raft_logs > 10000 {
self.handle_log_lag(report.region_id);
}
}
fn handle_no_leader(&self, region_id: u64) {
// 1. 选择候选节点
let candidates = self.find_available_stores();
// 2. 尝试强制选举
for store in candidates {
let op = Operator::ForceLeader {
region_id,
store_id: store.id,
};
if self.apply_operator(op).is_ok() {
return;
}
}
// 3. 创建新副本
self.create_new_replica(region_id);
}
}
八、性能优化技术
1. 批量处理优化
// raftstore/src/batch.rs
impl BatchSystem {
fn run(&mut self) {
let mut batch = Vec::with_capacity(BATCH_SIZE);
// 1. 批量收集消息
for _ in 0..BATCH_SIZE {
if let Some(msg) = self.receiver.try_recv() {
batch.push(msg);
} else {
break;
}
}
// 2. 按Region分组
let grouped = group_messages_by_region(batch);
// 3. 并行处理
for (region_id, messages) in grouped {
self.workers[region_id % WORKER_COUNT].send(messages);
}
}
}
2. 跨 Region 并行处理
九、核心源码模块
| 模块 | 源码路径 | 功能说明 |
|---|---|---|
| Region 管理 | raftstore/store/region/ | Region 元数据管理 |
| Raft 核心 | raft-rs/ | Raft 算法实现 |
| Peer 处理 | raftstore/store/peer.rs | Region 副本处理逻辑 |
| 调度器 | pd/server/schedulers/ | Region 调度策略 |
| 事务协调 | storage/txn/ | 分布式事务实现 |
| 批量系统 | raftstore/batch.rs | 消息批量处理 |
十、生产实践建议
-
Region 大小优化:
# 建议配置 coprocessor.region-split-size = "96MB" coprocessor.region-split-keys = 1000000 -
热点 Region 处理:
-- 手动拆分热点Region SPLIT REGION region_id BY 'split_key'; -- 手动迁移Region SCHEDULE OPERATOR ADD TRANSFER-LEADER region_id TO store_id; -
监控关键指标:
# Region分布 tiup ctl pd region --jq=".regions | group_by(.store_id)" # 热点检测 tiup ctl pd hotspot
TiKV 的 Multi-Raft 机制通过将数据分片成多个 Region,每个 Region 由独立的 Raft Group 管理,实现了:
- 水平扩展:数据分散到多个 Raft Group
- 故障隔离:单个 Group 故障不影响其他
- 负载均衡:PD 动态调度 Region
- 高吞吐:并行处理多个 Group 请求
这种设计使 TiKV 能够支持超大规模集群(1000+ 节点)和 PB 级数据存储,同时保持强一致性和高可用性。
本文来自博客园,作者:NeoLshu,转载请注明原文链接:https://www.cnblogs.com/neolshu/p/19120339

浙公网安备 33010602011771号