MIT6.5840-2023-Lab2B: Raft-Log

2023-12-13 05:12
文章标签 2023 log raft mit6.5840 lab2b

本文主要是介绍MIT6.5840-2023-Lab2B: Raft-Log,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前置知识

见上一篇 Lab2A。

实验内容

实现 RAFT,分为四个 part:leader election、log、persistence、log compaction。

实验环境

OS:WSL-Ubuntu-18.04
golang:go1.17.6 linux/amd64

Part 2B: log

这部分主要实现添加新的 log。

日志匹配特性(Log Matching Property)

  • 如果在不同的日志中的两个条目拥有相同的索引和任期号,那么他们存储了相同的指令。
  • 如果在不同的日志中的两个条目拥有相同的索引和任期号,那么他们之前的所有日志条目也全部相同。

第一个特性来自这样的一个事实,领导人最多在一个任期里在指定的一个日志索引位置创建一条日志条目,同时日志条目在日志中的位置也从来不会改变。第二个特性由附加日志 RPC 的一个简单的一致性检查所保证。在发送附加日志 RPC 的时候,领导人会把新的日志条目前紧挨着的条目的索引位置和任期号包含在日志内。如果跟随者在它的日志中找不到包含相同索引位置和任期号的条目,那么他就会拒绝接收新的日志条目。一致性检查就像一个归纳步骤:一开始空的日志状态肯定是满足日志匹配特性的,然后一致性检查在日志扩展的时候保护了日志匹配特性。因此,每当附加日志 RPC 返回成功时,领导人就知道跟随者的日志一定是和自己相同的了。

Start:
向 leader 添加log;

客户端的每一个请求都包含一条被复制状态机执行的指令。领导人把这条指令作为一条新的日志条目附加到日志中去(此时请求返回指令在日志中的 index,但不保证指令被提交;Start 函数返回了,随着时间的推移,对应于这个客户端请求的 ApplyMsg 从applyCh channel 中出现在了 key-value 层。只有在那个时候,key-value 层才会执行这个请求,并返回响应给客户端),然后并行地发起 AppendEntries RPCs 给其他的服务器,让他们复制这条日志条目。当这条日志条目被安全地复制,领导人会应用这条日志条目到它的状态机中然后把执行的结果返回给客户端。如果跟随者崩溃或者运行缓慢,再或者网络丢包,领导人会不断的重复尝试 AppendEntries RPCs (尽管已经回复了客户端)直到所有的跟随者都最终存储了所有的日志条目。

func (rf *Raft) Start(command interface{}) (int, int, bool) {index := -1term := -1isLeader := true// Your code here (2B).rf.mu.Lock()term = rf.currentTermisLeader = rf.state == Leaderif !isLeader {rf.mu.Unlock()return index, term, isLeader}log.Println(rf.me, "Start", "rf.currentTerm", rf.currentTerm, "command", command, "len(rf.log)", len(rf.log))rf.log = append(rf.log, Entry{Command: command,Term:    term,})rf.nextIndex[rf.me] = len(rf.log)rf.matchIndex[rf.me] = len(rf.log) - 1rf.persist()index = len(rf.log) - 1rf.mu.Unlock()go rf.replicateLog() // replicate log to followerreturn index, term, isLeader
}

commit:
更新 commitIndex。

领导人知道一条当前任期内的日志记录是可以被提交的,只要它被存储到了大多数的服务器上。Raft 永远不会通过计算副本数目的方式去提交一个之前任期内的日志条目。只有领导人当前任期里的日志条目通过计算副本数目可以被提交;一旦当前任期的日志条目以这种方式被提交,那么由于日志匹配特性,之前的日志条目也都会被间接的提交。

func (rf *Raft) commit() {rf.mu.Lock()defer rf.mu.Unlock()if rf.state != Leader {return}for N := len(rf.log) - 1; N > rf.commitIndex; N-- {if rf.log[N].Term != rf.currentTerm {return}num := 0for i := 0; i < len(rf.matchIndex); i++ {if rf.matchIndex[i] >= N {num++}}if num > len(rf.peers)/2 {rf.commitIndex = Nlog.Println(rf.me, "commit", "rf.commitIndex", rf.commitIndex, "len(rf.log)", len(rf.log))return}}
}

apply:
当 commitIndex 落后 lastApplied,向 applyCh 传输 command。

func (rf *Raft) apply() {for rf.killed() == false {rf.mu.Lock()if rf.commitIndex > rf.lastApplied {savedLastApplied := rf.lastAppliedlogEntries := rf.log[rf.lastApplied+1 : rf.commitIndex+1]rf.lastApplied = rf.commitIndexfor i, entry := range logEntries {log.Println(rf.me, "apply", "rf.commitIndex", rf.commitIndex, "rf.lastApplied", rf.lastApplied, "command", entry.Command)rf.applyCh <- ApplyMsg{CommandValid: true,Command:      entry.Command,CommandIndex: savedLastApplied + i + 1,}}}// if rf.commitIndex > rf.lastApplied {// 	log.Println(rf.me, "apply", "rf.commitIndex", rf.commitIndex, "rf.lastApplied", rf.lastApplied, "command", rf.log[rf.lastApplied+1].Command)// 	rf.lastApplied++// 	rf.applyCh <- ApplyMsg{// 		CommandValid: true,// 		Command:      rf.log[rf.lastApplied].Command,// 		CommandIndex: rf.lastApplied,// 	}// }rf.mu.Unlock()time.Sleep(time.Duration(10) * time.Millisecond)}
}

这篇关于MIT6.5840-2023-Lab2B: Raft-Log的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/487247

相关文章

内核启动时减少log的方式

内核引导选项 内核引导选项大体上可以分为两类:一类与设备无关、另一类与设备有关。与设备有关的引导选项多如牛毛,需要你自己阅读内核中的相应驱动程序源码以获取其能够接受的引导选项。比如,如果你想知道可以向 AHA1542 SCSI 驱动程序传递哪些引导选项,那么就查看 drivers/scsi/aha1542.c 文件,一般在前面 100 行注释里就可以找到所接受的引导选项说明。大多数选项是通过"_

CSP 2023 提高级第一轮 CSP-S 2023初试题 完善程序第二题解析 未完

一、题目阅读 (最大值之和)给定整数序列 a0,⋯,an−1,求该序列所有非空连续子序列的最大值之和。上述参数满足 1≤n≤105 和 1≤ai≤108。 一个序列的非空连续子序列可以用两个下标 ll 和 rr(其中0≤l≤r<n0≤l≤r<n)表示,对应的序列为 al,al+1,⋯,ar​。两个非空连续子序列不同,当且仅当下标不同。 例如,当原序列为 [1,2,1,2] 时,要计算子序列 [

HNU-2023电路与电子学-实验3

写在前面: 一、实验目的 1.了解简易模型机的内部结构和工作原理。 2.分析模型机的功能,设计 8 重 3-1 多路复用器。 3.分析模型机的功能,设计 8 重 2-1 多路复用器。 4.分析模型机的工作原理,设计模型机控制信号产生逻辑。 二、实验内容 1.用 VERILOG 语言设计模型机的 8 重 3-1 多路复用器; 2.用 VERILOG 语言设计模型机的 8 重 2-1 多

ImportError: cannot import name ‘print_log‘ from ‘logging‘

mmcv升级到2.+后删除了很多 解决 查FAQ文档,找到 添加到mmcv.utils下即可

DAY16:什么是慢查询,导致的原因,优化方法 | undo log、redo log、binlog的用处 | MySQL有哪些锁

目录 什么是慢查询,导致的原因,优化方法 undo log、redo log、binlog的用处  MySQL有哪些锁   什么是慢查询,导致的原因,优化方法 数据库查询的执行时间超过指定的超时时间时,就被称为慢查询。 导致的原因: 查询语句比较复杂:查询涉及多个表,包含复杂的连接和子查询,可能导致执行时间较长。查询数据量大:当查询的数据量庞大时,即使查询本身并不复杂,也可能导致

多数据源的事务处理总是打印很多无用的log日志

之前做了一个项目,需要用到多数据源以及事务处理,在使用事务处理,服务器总是打印很多关于事务处理的log日志(com.atomikos.logging.Slf4jLogger),但是我们根本不会用到这些log日志,反而使得查询一些有用的log日志变得困难。那要如何屏蔽这些log日志呢? 之前的项目是提高项目打印log日志的级别,后来觉得这样治标不治本。 现在有一个更好的方法: 我使用的是log

2023 CCPC(秦皇岛)现场(第二届环球杯.第 2 阶段:秦皇岛)部分题解

所有题目链接:Dashboard - The 2023 CCPC (Qinhuangdao) Onsite (The 2nd Universal Cup. Stage 9: Qinhuangdao) - Codeforces 中文题面: contest-37054-zh.pdf (codeforces.com) G. Path 链接: Problem - G - Codeforces

log file sync等待事件

概念: 1、REDO组件: redolog buffer=>位于SGA中,是一块循环使用的内存区域,保存数据库变更的相关信息并以重做条目redoentries形式存储,包含DML及DDL语句; LGWR=>通过此进程把redo buffer的内容写到redo log file中; redo log file=>(在归档模式下被ARC n最终写入归档日志)。最少两组重做日志,每组最少

git 学习的流水log

git命令联系 配置以及修改全局user信息 git config --global user.name 'you_name' git config --global user.email 'you_email@qq.com' 现有设备中的所有配置 git config --list 现有设备中的所有配置 git config --list --local/--global/--syste

HNU-2023电路与电子学-实验1

写在前面: 这是电路与电子学课程的第一次实验,按照指导书的需求在Multisim软件搭建一个电路传感器模型,难度较小,细心完成就没有问题。 小tips:22级实验是采用上传到测试平台来进行功能检测,如果不通过则会打回修改后再重新提交,(我们那时候的评测系统特别特别慢,一次只能测一个同学,剩下同学就排队等着,久的时候甚至超过10个小时),这里列举一个常见的错误:热噪声有+号这端需要连接有源滤波器