文章中如果有图看不到,可以点这里去 csdn 看看。从那边导过来的,文章太多,没法一篇篇修改好。

TiKV Multi-Raft 机制深度解析

一、Multi-Raft 架构全景

1. Region 与 Raft Group 关系

分片
分片
分片
Leader
Follower
Follower
Leader
Follower
Follower
Leader
Follower
Follower
数据集
Region 1
Region 2
Region 3
Raft Group 1
Raft Group 2
Raft Group 3
Node A
Node B
Node C

2. 核心组件协作

TiKV Store
调度指令
心跳/报告
日志复制
状态机
数据
读写请求
RaftStore
Raft Groups
Storage Engine
RocksDB
Placement Driver
TiKV Store
Client

二、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 分裂过程

LeaderPDFollowerScheduler检测到Region过大分裂指令创建新Region元数据提交分裂日志确认分裂报告新Region更新路由表LeaderPDFollowerScheduler

三、RaftStore 架构设计

1. RaftStore 核心模块

StoreRouter
+send_msg(region_id, msg)
+broadcast(region_ids, msg)
Peer
+handle_raft_message()
+propose()
+on_ready()
RaftLogEngine
+append(entries)
+fetch(start_index)
+compact(to_index)
ApplyFsm
+apply_committed_entries()
+handle_snapshot()

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. 负载均衡算法

定期
PD
收集节点负载
计算Region得分
识别热点Region
生成调度计划
执行Region迁移

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 事务模型

ClientTiKVBegin()StartTSPut(k1,v1)Put(k2,v2)Commit()CommitTSClientTiKV

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 合并过程

PDSourceTarget发送合并指令确认准备就绪发送合并指令发起合并请求停止服务发送最后日志应用日志报告合并完成PDSourceTarget

七、故障恢复机制

1. Raft Group 恢复流程

Leader失效
Leader失效
成功
失败
成功
失败
节点故障
Raft Group 1
Raft Group 2
选举新Leader
选举新Leader
继续服务
PD介入调度
继续服务
PD介入调度

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 并行处理

结果聚合
并行处理
拆分
拆分
拆分
聚合器
处理线程1
Region 1
处理线程2
Region 2
处理线程3
Region 3
客户端请求
返回客户端

九、核心源码模块

模块源码路径功能说明
Region 管理raftstore/store/region/Region 元数据管理
Raft 核心raft-rs/Raft 算法实现
Peer 处理raftstore/store/peer.rsRegion 副本处理逻辑
调度器pd/server/schedulers/Region 调度策略
事务协调storage/txn/分布式事务实现
批量系统raftstore/batch.rs消息批量处理

十、生产实践建议

  1. Region 大小优化

    # 建议配置
    coprocessor.region-split-size = "96MB"
    coprocessor.region-split-keys = 1000000
    
  2. 热点 Region 处理

    -- 手动拆分热点Region
    SPLIT REGION region_id BY 'split_key';
    
    -- 手动迁移Region
    SCHEDULE OPERATOR ADD TRANSFER-LEADER region_id TO store_id;
    
  3. 监控关键指标

    # Region分布
    tiup ctl pd region --jq=".regions | group_by(.store_id)"
    
    # 热点检测
    tiup ctl pd hotspot
    

TiKV 的 Multi-Raft 机制通过将数据分片成多个 Region,每个 Region 由独立的 Raft Group 管理,实现了:

  1. 水平扩展:数据分散到多个 Raft Group
  2. 故障隔离:单个 Group 故障不影响其他
  3. 负载均衡:PD 动态调度 Region
  4. 高吞吐:并行处理多个 Group 请求

这种设计使 TiKV 能够支持超大规模集群(1000+ 节点)和 PB 级数据存储,同时保持强一致性和高可用性。

posted @ 2025-09-14 11:38  NeoLshu  阅读(4)  评论(0)    收藏  举报  来源