Multi-Raft 架构, 数据Shard分区,数据迁移

Raft 与 Multi Raft

PingCAP TiKV课程笔记课程链接

数据是以region(也叫Raft Group)为单位进行存储的。一个region默认会有3个副本,存在不同的TiKV Node上。副本中的一个节点为leader。所有的读写流量只走leader,leader定期向follower发送心跳,进行日志复制。

Region内部是一个kv map,按照key排序存储。相邻的region数据紧密相连。一个region的最大size为96M,一旦超出就自动存入新的region。

多个region/raft group就叫multi-raft

Raft 回顾

日志复制:

1. propose: 收到请求, 生成raft log (包含了请求内容以及编号(region#, log_index节点内部的日志编号))

2. append: 将日志存入本地的rocksdb中(专门存raft log),持久化raft log。

3. replicate:向其他follower传播,follower收到后也写入自己本地的rocksdb raft中持久化。

4. 当大多数节点都返回append成功的消息给leader后,leader就发出commited 命令,并且apply到真正的数据库上(把日志取出来,运用,即写到rocksdb kv中)。其他follower在收到commit命令后也将日志转移到自己的apply pool,之后持久化到rocksdb kv.

Leader选举

时间在raft看来是一段一段的term。term内是一段稳定的状态。

当election timeout了,进入选举。

选举成功,变为leader,发送heartbeat timeout。

选举的活锁问题

资料参考:分布式一致性协议之Raft的实现详解-腾讯云开发者社区-腾讯云

leader被选出来,某个其他节点又启动一轮选举

选主过程中,可能出现多个节点同时发起选主的情况,这样导致选票瓜分,无法选出主,在下一轮选举中依旧如此,导致系统状态无法往前推进。Raft通过随机超时解决这个“活锁”问题。

安全性

  • Raft协议中有哪些重要的安全性质?如何保证这些安全性质?

    • 选举安全性: Election Safety

      • Follower在一个任期内只投一次票, 只能投任期比自己新,日志至少要和自己一样的candidate

      • 必须获得超半数投票成为leader

    • 日志 Append-Only

      • 只有leader有 append entries请求发送权力

      • Leader只可追加log,不可覆盖log

      • 一致性检查:每条log包含(term, index)

    • 日志匹配特性 Log Matching

      • 保证日志唯一性,

      • 两个不同机器,若分别有(term, index)相同的log,则log内容必须相同

      • 两个不同机器,若分别有(term, index)相同的log,该log之前的所有entries也要相同

    • Leader 完备性 Leader Completeness

      • Leader必须具备最新提交log

      • Candidate竞选投票时会携带最新提交日志,Follower会用自己的日志和Candidate做比较,如果Follower的日志比Candidate还新,那么拒绝这次投票

      • 新:

        • 如果Term不同,选择Term值最大的

        • 如果Term相同,选择Index值最大的

    • 状态及安全性 State Machines Safety

      • 一个log被复制到超半数节点才算提交成功

      • Leader只能提交当前term的日志

成员变更

成员变更解释

任何一个节点收到了成员变更配置 ConfChange,只要把它持久化了,就可以直接生效,无需和传统日志一样需要先 commit,然后等待 apply 时应用。

保证变更前后的 quorum 存在交集,即保证了整个集群自始至终只会存在一个 leader,以此来保证正确性。Joint Consensus 通过一个中间阶段保证每一步变更的 quorum 比如存在交集

一次读写请求怎么完成

数据的写入

raftstore pool是线程池,接受用户写请求,序列化为日志之后持久化到rocksdb raft,replicate到其他节点,log转移到apply pool(也是一个线程池),最终修改rocksdb kv里的实际内容。

写入成功不代表能够读到,原因在于apply操作的滞后性。

数据的读取

复习快照隔离级别:保证读请求不会出现幻读,并发写请求只有一个生效。

有两个问题:

1. 数据一致性:考虑apply滞后

        解决方法: ReadIndex Read, 先记录最近一次提交的编号(ReadIndex),再等待最近一次apply(ApplyIndex)与ReadIndex相等。

2.读取过程中成员变更:考虑leader宕机/成员变更

        解决方法:在使用ApplyIndex读取前要先发一次心跳,如果仍然是leader就放心读

改进2的解决方法,避免多次网络操作询问自己是否是leader:

        Lease Read: 通过计算绝对不可能变更leader的时间段(上次心跳到不发心跳到election timeout)

Follower Read 分摊leader压力:

follower接到请求,问leader最新commit的log编号CommitIndex,知道了leader提交到哪了。看自己本地的ApplyIndex,如果没赶上就等,直到赶上leader的复制进度CommitIndex。好处是有可能leader提交比follower慢呢,这样follower read就能快点拿到读取结果。

范围搜索

Multi-Raft的调度

相关资料:

思路很清晰的博客系列,以后多多阅读大佬的blog

很好的学习资料: TiKV源码解析multi raft部分

Place Driver

PD的作用是region管理(负责数据副本在region中的调度)和TSO全局时钟的分配。

1. 路由功能:负责查找元数据

2. 给大量高并发的请求分配TSO全局时钟,并保证单调递增

3. 收集集群信息(比如检查热点进行region迁移)

4. 提供label功能支持高可用

数据分区算法:hash/range

Region的定义,这里使用TiKV为例:

message Region {
    optional uint64 id                  = 1 [(gogoproto.nullable) = false];
    optional bytes  start_key           = 2;
    optional bytes  end_key             = 3;
    optional RegionEpoch region_epoch   = 4;
    repeated Peer   peers               = 5;
}
message RegionEpoch {
    optional uint64 conf_ver    = 1 [(gogoproto.nullable) = false];
    optional uint64 version     = 2 [(gogoproto.nullable) = false];
}
message Peer {
    optional uint64 id          = 1 [(gogoproto.nullable) = false];
    optional uint64 store_id    = 2 [(gogoproto.nullable) = false];
}

比较重要的Raft类型

PeerState

message RaftLocalState {
    optional eraftpb.HardState hard_state        = 1;
    optional uint64 last_index                  = 2;
}
message RaftApplyState {
    optional uint64 applied_index               = 1;
    optional RaftTruncatedState truncated_state = 2;
}
enum PeerState {
    Normal       = 0;
    Applying     = 1;
    Tombstone    = 2;
}
message RegionLocalState {
    optional PeerState state        = 1;
    optional metapb.Region region   = 2;
}

Raft硬状态:1. 当前任期号 2. 已投票给候选人ID 3. 日志索引

LocalState last index指最后一个Log Index

SnapShot: 

pub enum SnapState {
    Relax,
    Generating(Receiver<Snapshot>),
    Applying(Arc<AtomicUsize>),
    ApplyAborted,
}

在Raft算法中,快照(Snapshot)的处理是对系统性能和响应时间非常重要的一个方面。因为快照操作涉及到将当前状态机的状态持久化存储,这可能包括大量的数据,因此通常是耗时的操作。为了确保快照处理不会阻塞整个Raft线程,需要采用一些策略来优化这个过程。

`PeerStorage`的快照状态管理(`SnapState`枚举)就是这种优化的一个例子。这里的策略包括:

- **Relax**: 表示没有快照操作正在进行,系统处于正常状态。

- **Generating(Receiver<Snapshot>)**: 表示快照正在生成中。此状态使用`Receiver<Snapshot>`来异步接收生成的快照数据。这允许快照生成过程在后台进行,不会阻塞主Raft进程。

- **Applying(Arc<AtomicUsize>)**: 表示快照正在应用中。快照应用是一个将快照数据加载到状态机中的过程,这同样可能是一个耗时操作。通过使用`Arc<AtomicUsize>`,可以在不同线程中安全地共享和管理快照的应用状态,同时允许这个过程异步执行。

- **ApplyAborted**: 表示快照应用过程被中断或放弃。这可能发生在系统决定放弃当前的快照应用过程,可能是因为接收到了一个更新的快照,或者因为其他原因需要停止当前的快照应用。

Peer

Peer里完成propose, ready等操作

command类型:

1. 只读,如果leader在lease有效期内,就能直接提供local read。

2. transfer read: 是否follower有足够新的log

3. Change Peer调用RawNode

propose之前会将callback(回调)存到PendingCmd里面,以便后续完成propose返回客户端

handle_raft_ready:负责将entries写入storage,发送messages, apply committed_entries以及advance

Multi Raft

对于一个store需要管理多个region副本

region_peers: HashMap<u64, Peer>

RawNode tick函数驱动Raft,需要注册一个Raft Tick

tick回调回进行 on_raft_ready的处理:

  1. Store 会遍历所有的 ready Peers,调用 handle_raft_ready_append,我们会使用一个 WriteBatch 来处理所有的 ready append 数据,同时保存相关的结果。
  2. 如果 WriteBatch 成功,会依次调用 post_raft_ready_append,这里主要用来处理Follower 的消息发送(Leader 的消息已经在 handle_raft_ready_append 里面完成)。
  3. 然后,Store 会依次调用 handle_raft_ready_apply,apply 相关 committed entries,然后调用 on_ready_result 处理最后的结果。

Server: 

对网络IO的处理,TiKV网络层,封装 message (header + body),编码

流程和socket网络接口有点像:

1. bind 端口,生成一个用于交互的对象

2. 使用TcpStream和客户端交互

3. TcpStream处理回调

对于受到的message,都有对应的处理线程

模模糊糊理解了一些!继续学习

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/476879.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

docker 修改日志存储路径

docker 日志默认存放在 /var/lib/docker/ 下 docker info修改步骤&#xff1a; 1、停止docker服务 systemctl stop docker 2、新建配置文件 vi /etc/docker/daemon.json添加如下内容 {"data-root": "/data/docker" }3、然后把之前的数据全部复制到新目…

基于Springboot的高校图书馆座位预约系统+数据库+报告+免费远程调试

开发语言&#xff1a;Java 开发工具:IDEA /Eclipse 数据库:MYSQL5.7 使用框架:springbootvue JDK版本&#xff1a;jdk1.8 项目介绍: 基于Springboot的高校图书馆座位预约系统。Javaee项目&#xff0c;springboot项目。采用M&#xff08;model&#xff09;V&#xff08;view&…

关于在CentOS中卸载MySQL

想要卸载MySQL当然要知道自己的MySQL是用那种方法来安装的了&#xff0c;一般来说MySQL的安装方法在市面上有三种 编译安装、YUM安装、RPM安装&#xff0c;下面会介绍到后两种安装的卸载方法 首先查看是否安装MySQL&#xff0c;一般可以看到版本信息就证明安装了 mysql -V 卸载…

Vue3 大量赋值导致reactive响应丢失问题

问题阐述 如上图所示&#xff0c;我定义了响应式对象arrreactive({data:[]})&#xff0c;尝试将indexedDB两千条数据一口气赋值给arr.data。但事与愿违&#xff0c;页面上的{{}}在展示先前数组的三秒后变为空。 问题探究 vue3的响应应该与console.log有异曲同工之妙&#xff0…

2024开年首展,加速科技展台“热辣滚烫”

3月20日&#xff0c;备受瞩目的半导体行业盛会SEMICON China 2024在上海新国际博览中心盛大启幕&#xff0c;展会汇集了来自全球的半导体领域顶尖企业与专业人士。加速科技作为业界领先的半导体测试设备供应商携重磅测试设备及解决方案精彩亮相&#xff0c;展示了最新的半导体测…

如何实现手机遥控端关机按钮同时关闭TV端和手机端界面

目前家庭电视机主要通过其自带的遥控器进行操控&#xff0c;实现的功能较为单一。例如&#xff0c;当我们要在TV端搜索节目时&#xff0c;电视机在遥控器的操控下往往只能完成一些字母或数字的输入&#xff0c;而无法输入其他复杂的内容。分布式遥控器将手机的输入能力和电视遥…

pandas读写excel,csv

1.读excel 1.to_dict() 函数基本语法 DataFrame.to_dict (self, orientdict , into ) --- 官方文档 函数种只需要填写一个参数&#xff1a;orient 即可 &#xff0c;但对于写入orient的不同&#xff0c;字典的构造方式也不同&#xff0c;官网一共给出了6种&#xff0c…

为什么3D开发要用三维模型格式转换工具HOOPS Exchange?

在当今数字化时代&#xff0c;3D技术在各个行业中扮演着愈发重要的角色&#xff0c;从产品设计到制造、建筑、医疗保健等领域。然而&#xff0c;由于不同的软件和系统使用不同的3D模型格式&#xff0c;跨平台、跨系统之间的数据交换和共享变得十分复杂。为了解决这一难题&#…

利用Python进行数据清洗与预处理:Pandas的高级用法【第147篇—Pandas的高级用法】

&#x1f47d;发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 利用Python进行数据清洗与预处理&#xff1a;Pandas的高级用法 在数据科学和机器学习领域&…

浅浅迈入C++门槛

从今天起&#xff0c;我要开始hello&#xff0c;world。 往后更要做到&#xff0c;拳打数据结构&#xff0c;脚踢Linux。 这就是江湖人的风范。 拼搏百天&#xff0c;我要学希普拉斯普拉斯。 C是在C的基础之上&#xff0c;容纳进去了面向对象编程思想&#xff0c;并增加了许…

基于单片机的四旋翼飞行器的设计与实现

摘 要:四旋翼飞行器可以垂直升降,应用于军事和民用领域,在飞行器的设计中,结合单片机进行设计,可以提升整体性能。基于此,本文探究基于单片机的四旋翼飞行器设计与实现,探索飞行器的硬件设计和软件设计方案,并且对系统的角速度算法以及姿态控制算法进行测试,最后对系…

【题目】【网络系统管理】2019年全国职业技能大赛高职组计算机网络应用赛项H卷

极安云科专注职业教育技能竞赛培训4年&#xff0c;包含信息安全管理与评估、网络系统管理、网络搭建等多个赛项及各大CTF模块培训学习服务。本团队基于赛项知识点&#xff0c;提供完整全面的系统性理论教学与技能培训&#xff0c;成立至今持续优化教学资源与讲师结构&#xff0…

【QT+QGIS跨平台编译】之八十五:【QGIS_Gui跨平台编译】—【错误处理:Qt5UiTools - Qt5UiTools】

文章目录 一、错误信息二、错误处理 一、错误信息 二、错误处理 定位到Qt5iTools目录。(例如&#xff1a;/Users/lucky/Qt/5.15.2/clang_64/lib&#xff09; 拷贝libQt5UiTools.a&#xff0c;粘贴为&#xff1a;libQt5UiTools_debug.a

基于Matlab的视频人体动作识别,Matlab实现

博主简介&#xff1a; 专注、专一于Matlab图像处理学习、交流&#xff0c;matlab图像代码代做/项目合作可以联系&#xff08;QQ:3249726188&#xff09; 个人主页&#xff1a;Matlab_ImagePro-CSDN博客 原则&#xff1a;代码均由本人编写完成&#xff0c;非中介&#xff0c;提供…

【HM】STM32F407 HAL库 PWM

PWM简介 脉冲宽度调制&#xff08;PWM&#xff09; 是一种数字信号&#xff0c;最常用于控制电路。该信号在预定义的时间和速度中设置为高&#xff08;5v或3.3v&#xff09;和低&#xff08;0v&#xff09;。通常&#xff0c;我们将PWM的高电平称为1&#xff0c;低电平为0。 …

解锁人工智能新境界:大模型工程与架构的深度探索

在当今世界&#xff0c;人工智能(AI)无处不在&#xff0c;它已经悄然改变了我们的生活方式。从自动驾驶汽车到智能音箱&#xff0c;从智能医疗系统到虚拟助手&#xff0c;AI的影子无处不在。而在这一切背后&#xff0c;是一个个巨大的数学模型在默默运转。这些模型就像是我们人…

excel所有知识点

1要加双引号 工作表&#xff08;.xlsx) 单击右键→插入&#xff0c;删除&#xff0c;移动、重命名、复制、设置标签颜色&#xff0c;选定全部工作表 工作表的移动&#xff1a;两个表打开→右键→移动&#xff08;如果右键是灰色的&#xff0c;可能是保护工作表了&#xff09…

JAVA安全(偏基础)

SQL注入 SQLI(SQL Injection)&#xff0c; SQL注入是因为程序未能正确对用户的输入进行检查&#xff0c;将用户的输入以拼接的方式带入SQL语句&#xff0c;导致了SQL注入的产生。攻击者可通过SQL注入直接获取数据库信息&#xff0c;造成信息泄漏。 JDBC JDBC有两个方法获取s…

鸿蒙Harmony应用开发—ArkTS-全局UI方法(列表选择弹窗)

列表弹窗。 说明&#xff1a; 从API Version 8开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 本模块功能依赖UI的执行上下文&#xff0c;不可在UI上下文不明确的地方使用&#xff0c;参见UIContext说明。 从API version 10开始&#xff0…

hadoop学习笔记

hadoop概述 Apache Hadoop 为可靠的&#xff0c;可扩展的分布式计算开发开源软件。作为一个数据框架允许使用简单的编程模型跨计算机群集分布式处理大型数据集&#xff08;海量的数据&#xff09;。分别由一下三个模块组成&#xff1a; 1、Hadoop分布式文件系统&#xff08;HDF…