//1.實現(xiàn)3節(jié)點選舉
//2.改造代碼成分布式選舉代碼,加入Rpc調(diào)用
//3.演示完整代碼 自動選主 日志復(fù)制
//定義3節(jié)點常量
const raftCount =3
/**
Leader對象
Term int 任期 還沒上任為0
LeaderId int leaderId 編號 沒有編號為-1
*/
type Leader struct {
Term int
LeaderId int
}
/**raft的聲明
鎖 mu sync.Mutex
節(jié)點編號 me int
當(dāng)前任期 currentTerm int
為哪個節(jié)點投票 -1代表誰都不投 vatedFor int
0.follower 1.candidate 2.leader state int
發(fā)送最后一條消息的時間 lastMessaheTime int64
當(dāng)前節(jié)點的leader currentLeader int
節(jié)點間發(fā)送信息的通道 message chan bool
選舉通道 electCh chan bool
心跳信號的通道 heartBeat chan bool
返回心跳信號的通道 heartbeatRe chan bool
超時時間 timeout int
*/
type Raft struct{
mu sync.Mutex
me int
currentTerm int
votedFor int
state int
lastMessaheTime int64
currentLeader int
message chan bool
electCh chan bool
heartBeat chan bool
heartbeatRe chan bool
timeout int
}
var leader = Leader{0,-1}
func main() {
//過程:有三個節(jié)點,最初都是follower
//如果有candidate狀態(tài),進行投票和拉票
//會產(chǎn)生leader
//會產(chǎn)生3個節(jié)點
for i:=0;i<raftCount;i++{
//穿件三個raft節(jié)點
Make(i)
}
}
func Make(me int ) *Raft {
rf:=&Raft{}
rf.me=me
rf.votedFor=-1
rf.state=0
rf.timeout=0
rf.currentLeader=-1
rf.setTerm(0)
rf.message=make(chan bool)
rf.electCh=make(chan bool)
rf.heartBeat=make(chan bool)
rf.heartbeatRe=make(chan bool)
//設(shè)置隨機種子
rand.Seed(time.Now().UnixNano())
//選舉協(xié)程
go rf.election()
//心跳檢測協(xié)程
go rf.sendLeaderHeartBeat()
return rf
}
/** setTerm for currentTerm
for Raft struct
params term int which one item number
*/
func (rf *Raft)setTerm(term int ){
rf.currentTerm=term
}
/** election for leader
*/
func (rf *Raft)election() {
var result bool
for {
timeout :=randRage(150,300)
rf.lastMessaheTime=millisecond()
select {
case <-time.After(time.Duration(timeout)*time.Microsecond):
fmt.Println("當(dāng)前節(jié)點狀態(tài)為:",rf.state)
}
result=false
for !result{
result=rf.election_one_round(&leader)
}
}
}
/* randRange set time out
*/
func randRage(min,max int64) int64 {
return rand.Int63n(max-min)+min
}
/**get the lastMessage send time
*/
func millisecond() int64 {
return time.Now().UnixNano()/int64(time.Microsecond)
}
/**
implementation of select leader
*/
func (rf *Raft)election_one_round(leader *Leader) bool {
//set time out
var timeout int64
timeout = 100
//number of vote
var vote int
//heartbeat
var triggerHeartbeat bool
var success bool
//time
last :=millisecond()
//change the item be canditate
rf.mu.Lock()
//change state
rf.becomeCandidate()
rf.mu.Unlock()
fmt.Println("staet electing leader")
//range all item
for{
for i:=0;i<raftCount;i++ {
if i!=rf.me{
// canvass vote
go func() {
if leader.LeaderId<0{
rf.electCh<-true
}
}()
}
}
vote = 1
for i:=0;i<raftCount;i++{
//calculate the number of vote
select {
case ok:=<-rf.electCh:
if ok{
//vote number add 1
vote++
//if vote great than node one-second ,successful
success=vote>raftCount/2
if success&&!triggerHeartbeat{
//change be the leader success
//trigger the hearbeat detection
triggerHeartbeat =true
rf.mu.Lock()
rf.becomeLeader()
rf.mu.Unlock()
rf.heartBeat<- true
fmt.Println(rf.me,"號節(jié)點成為leader")
fmt.Println("leader 開始發(fā)送心跳信號")
}
}
}
}
//final check
//if don't time out and the vote great then node one-second ,than impelmention select leader successful.
if timeout+last<millisecond()||(vote>raftCount/2||rf.currentLeader>-1){
break
}else{
select {
case <-time.After(time.Duration(10)*time.Microsecond):
}
}
}
return success
}
/**
change state with candidate
*/
func (rf *Raft)becomeCandidate() {
rf.state=1
rf.setTerm(rf.currentTerm+1)
rf.votedFor=rf.me
rf.currentLeader=-1
}
/**
change state with leader
*/
func(rf *Raft)becomeLeader(){
rf.state=2
rf.currentLeader=rf.me
}
/**
leader send heartBeat
complete data synchronization
*/
func (rf *Raft) sendLeaderHeartBeat() {
//infinity loop
for{
select {
case <-rf.heartBeat:
rf.sendAppendEntriesImpl()
}
}
}
/**
return info to the leader
*/
func (rf *Raft)sendAppendEntriesImpl() {
if rf.currentLeader == rf.me{
//the time is leader
//number of record to confirm single node
var success_count =0
for i:=0;i<raftCount;i++{
if i!=rf.me{
go func() {
rf.heartbeatRe<-true
}()
}
//complete the sigle node of return confirm
for i:=0;i<raftCount;i++{
select {
case ok:=<-rf.heartbeatRe:
if ok{
success_count++
if success_count>raftCount/2{
fmt.Println("投票選舉成功,心跳信號Ok")
log.Fatal("程序結(jié)束")
}
}
}
}
}
}
}
raft 算法實現(xiàn)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
- 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
- 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
- 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
- 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
- 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
- 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
推薦閱讀更多精彩內(nèi)容
- etcd 是一個分布式的、可靠的 key-value 存儲系統(tǒng),它用于存儲分布式系統(tǒng)中的關(guān)鍵數(shù)據(jù),這個定義非常重要...
- 記錄了疫情期間讀的raft實現(xiàn)論文筆記 全系列介紹了raft算法原理,實現(xiàn)過程,以及難點如果解決 從一開始不理解,...
- Raft是一個分布式系統(tǒng)的一致性算法,它不像Paxos那么難懂,實現(xiàn)比Paxos簡單許多,性能與Paxos相當(dāng),在...
- 1、前言 此工程實現(xiàn)來自 github 鏈接:https://github.com/stateIs0/lu-raf...
- 一、快速了解Raft算法 Raft 適用于一個管理日志一致性的協(xié)議,相比于 Paxos 協(xié)議 Raft 更易于理解...