MIT 6.824 Lab2 Raft (3)
在part A和part B当中,基本的将raft的东西都完成了。part C主要做的就是持久化的内容,也就是要将raft的一些状态信息保存下来,另外part C的测试脚本会模拟极端混乱的网络情况,并且会运行1000次,所以要对前面的代码做一个优化,不然无法通过part C。总的来说,part C要增加的代码不多,主要是持久化raft状态,以及一些…
MIT 6.824 Lab2 Raft (2)
Log Replication 基本的leader选举还是比较简单的,对于日志备份相比来说就是困难很多了。涉及到一些选举的优化,日志丢失的处理,以及一些现实中会出现的情况,比如说很多log entry丢失,导致log entry不能commit,leader掉线的日志的处理等内容。 我的2B代码中只是提供了最简单的实现,还有一些优化的空间,在2B中…
MIT 6.824 Lab2 Raft (1)
本文主要解释6.824中 lab2 Raft的part A和Part B部分。源代码链接:2A的代码,2B的代码 在这里,我不想讲述论文中的细节问题,只关注于如何实现代码,以及在编码的过程中可能需要考虑到的一些情况。 Leader Selection part A就是解决最简单的选举问题。所以对于论文中的figure 2中很多变量都是暂时不需要的。…
动态链接和静态链接
如果有过Linux编程的经验,基本上每个人都会看到过.o文件,.a文件,.so文件。一直没有认真的去了解过这些文件的区别。这些文件通常会在库文件中看到。比如说C语言的标准库。在任何一台Linux机器中,使用可以使用whereis命令来查找各个库文件的路径。下面是我在WSL中一个例子: 为了保持文章的完整性,我将.o文件也放到这里来一起讲解。 .o文…
CPU Cache
CPU Cache 缓存在现代计算机系统中有很大的作用。无论是CPU内的L1,L2,L3缓存,还是TLB缓存,还是内存上的对于一些应用数据的缓存。可以说缓存无处不在,CPU内的缓存可以让在运行的时候不需要多次去内存中取数据。那么为什么缓存能够为计算机系统带来这么大的好处呢? 归根到底就是,因为局部性(locality): 时间上的局部性 时间上的局…
惊群(thundering herd)
惊群(thundering herd) 本篇只是对惊群做一个实验性的学习.了解下epoll的为什么会产生惊群现象,并且可以如何处理.不过我的描述都是比较浅显的,暂时没有深入到内核中去学习. wiki-惊群 维基百科上对于惊群的解释是: In computer science, the thundering herd problem occurs w…
IO Multiplexing (二)
在前面一篇文章中,简要地介绍了在几个io多路复用的api的使用以及它们各自的优缺点.然而,对于epoll还有不少东西.如epoll的两种触发模式--边沿触发(edge trigger)和水平触发(level trigger).此外,epoll往往和非阻塞io搭配在一起使用,那么为什么epoll要和非阻塞io搭配在一起呢,是否有更好的效率呢? 本文用…
GoLang: Defer,Panic,Recover,Closure
GoLang: Defer,Panic,Recover,Closure 本文主要内容来自: GoLang Blog--Defer, Panic, and Recover GoLang Spec--Defer statements 接下来先简要的介绍defer,panic和recover的使用,最后在介绍一些defer和closure(闭包)组合在一…
Java并发编程基础
什么是线程 为了说明什么是线程,首先需要强调一点,什么是进程。所谓进程,就是正在运行的程序代码。每个进程之间是相互隔离的,两个进程有不同的栈,堆,寄存器组,PC,虚拟地址空间等。而线程是进程中更小的单位,与进程相类似,每一个线程也有他自己的context,包括它自己的寄存器,PC,栈等。但是一个线程会共享创建它的父进程的中的堆,打开的文件(即文件描…
volatile 关键字
因为CPU缓存的关系,以及指令的重排等等原因。有时候线程操作的变量往往是它从内存中复制过来到CPU缓存内的,所以修改完了如果没有flush到内存,那么可能会出现不一致。道理大概是这么个道理,在Java中,每个线程有自己的缓存大小,对于数据操作的时候,先操作线程内部的数据。所以其他线程对于该数据的变化看不到。所以引入了volatile 关键词来保证,…