基於etcd的選主功能實現的主備節點管理
etcd有多種使用場景,Master選舉是其中一種。本文主要講述如何使用etcd在多個service中選一個主服務。使用etcd選主和分散式鎖差不多,哪個service首先搶到某個值,誰就是主節點,選主介面是個同步介面,搶到主或者出現錯誤就返回,沒有搶到主的會一直阻塞。
pfx是字首,比如"/election/"
key類似於"/election/service1"
leaseID是一個64位的整數值,etcd v3引入了lease(租約)的概念,lease被封裝在session中,每一個客戶端都生成自己的lease,也就是說每個客戶端都有一個唯一的64位整形值。
val表示了當前主被誰獲得。獲取主的service依靠租約機制來維持主節點的有效性,租約預設有效期是60s,主servie不斷的續約就可以不斷的佔有主節點。
先來看clientv3/concurrency中自帶的選舉用例,閱讀這個用例之後我們大概就可以知道選舉的大概方法
func ExampleElection_Campaign() {
//建立v3的client端,我們和etcd的所有介面都是通過該client實現
cli, err := clientv3.New(clientv3.Config{Endpoints: endpoints})
if err != nil {
log.Fatal(err)
}
defer cli.Close()
//建立兩個競爭的Session,這裡Session有效期使用預設值60s
s1, err := concurrency.NewSession(cli)
if err != nil {
log.Fatal(err)
}
defer s1.Close()
//pfx 是"/my-election/"
e1 := concurrency.NewElection(s1, "/my-election/")
s2, err := concurrency.NewSession(cli)
if err != nil {
log.Fatal(err)
}
defer s2.Close()
//pfx 是"/my-election/"
e2 := concurrency.NewElection(s2, "/my-election/")
// create competing candidates, with e1 initially losing to e2
var wg sync.WaitGroup
wg.Add(2)
electc := make(chan *concurrency.Election, 2)
//啟動兩個goroutine,競爭主節點
go func() {
defer wg.Done()
// delay candidacy so e2 wins first
time.Sleep(3 * time.Second)
//節點名"e1"
if err := e1.Campaign(context.Background(), "e1"); err != nil {
log.Fatal(err)
}
electc <- e1
}()
go func() {
defer wg.Done()
if err := e2.Campaign(context.Background(), "e2"); err != nil {
log.Fatal(err)
}
electc <- e2
}()
cctx, cancel := context.WithCancel(context.TODO())
defer cancel()
// electc 返回說明有主選出來,沒選出來的goroutine會一直阻塞
e := <-electc
fmt.Println("completed first election with", string((<-e.Observe(cctx)).Kvs[0].Value))
// 當前的主節點主動離職
if err := e.Resign(context.TODO()); err != nil {
log.Fatal(err)
}
//又有新節點當選主主節點
e = <-electc
fmt.Println("completed second election with", string((<-e.Observe(cctx)).Kvs[0].Value))
wg.Wait()
// Output:
// completed first election with e2
// completed second election with e1
}
根據上面的簡單示例程式碼,大概清楚了選主的主要過程。
該如何應該這個選主機制呢?看下更復雜的場景下如何應用該選主機制,假設我們有三個service,需通過選主機制選出一個主,沒當選的降為備份節點。並且要滿足主節點切換需求。
我們將每個service內的主節點管理分成兩部分,選舉部分和監聽部分。
選舉部分負責選舉,監聽部分負責主備節點切換。
邏輯關係圖如下:
直接看程式碼吧,為了方便大家能看的更直觀,程式碼經過簡化處理。
func (s *service) Campaign(resign chan int) {
for {
//建立用於選舉的Session,有效時間可以根據實際情況設定。
session, err := createSession(s.Etcd.Client())
if err != nil {
//todo
continue
}
e := concurrency.NewElection(session, prefix)
s.election = e
if err = e.Campaign(context.Background(), s.SelfName); err != nil {
//todo
continue
}
//執行至此說明該節點當選主節點
s.IsMaster = true
s.SetLeader(s.SelfName)
cancel()
//超時監聽
select {
case <-session.Done():
s.IsMaster = false
s.ResetLeader()
//todo
case <-resign:
//todo
}
}
}
func (s *service) Leader Monitor () {
resign := make(chan int, 1)
//啟動選主協程
go s.Campaign(resign)
//監聽主從切換
for {
cctx, cancel := context.WithCancel(context.TODO())
ch := s.election.Observe(cctx)
for {
select {
case resp := <-ch:
if len(resp.Kvs) > 0 {
leader := string(resp.Kvs[0].Value)
if leader != s.SelfName {
if s.IsMaster {
s.IsMaster = false
}
s.SetLeader(leader)
}
} else {
cancel()
time.Sleep(time.Duration(public.MasterIntervalTime) * time.Second)
cctx, cancel = context.WithCancel(context.TODO())
ch = s.election.Observe(cctx)
}
}
}
}
}
相關文章
- 基於RabbitMQRPC實現的主機非同步管理MQRPC非同步
- 排序系統的主選單及功能實現排序
- 主庫RAC,備庫單節點ASM的dataguard搭建ASM
- Etcd叢集的介紹和選主應用
- 架構設計|基於 raft-listener 實現實時同步的主備叢集架構Raft
- 基於KubeEdge的邊緣節點分組管理設計與實現
- Etcd 使用場景:通過分散式鎖思路實現自動選主分散式
- Ext實現點選節點,父子節點反選
- 基於MySql主從分離的程式碼層實現MySql
- 簡述 zookeeper 基於 Zab 協議實現選主及事務提交協議
- Golang 基於單節點 Redis 實現的分散式鎖GolangRedis分散式
- oop主節點(NameNode)備份策略以及恢復方法OOP
- redis cluster 故障後,主從位於不同節點的修復。Redis
- 【DATAGUARD】 基於同一個主機建立物理備庫和邏輯備庫 (四)--新增一個物理dg節點
- Android主介面連續兩次點選物理返回鍵退出應用功能實現Android
- 基於keepalived Mysql雙主熱備配置MySql
- Android 設定主題實現點選波紋效果Android
- mysql 關於主鍵索引--節選丁奇部落格MySql索引
- 基於Masstransit實現Eventbus的功能
- hadoop主節點(NameNode)備份策略以及恢復方法Hadoop
- ZooKeeper系列(3)--基於ZooKeeper實現主從協作
- 【RAC】部署安裝RAC時確保主節點的時間小於其他節點時間
- mongodb主從仲裁節點配置MongoDB
- 學一點 mysql 雙機異地熱備份----快速理解mysql主從,主主備份原理及實踐MySql
- 使用Redis分散式鎖實現主備Redis分散式
- 主備都是全新的恢復,主主搭建步驟
- mysql之 mysql 5.6不停機主主搭建(活躍雙主基於日誌點複製)MySql
- 點選主介面 PopupMenu消失
- NoSQL 資料庫的主主備份SQL資料庫
- vmware基於主機模式實現上網(win10)模式Win10
- 使用Keepalived實現Nginx的雙機主備高可用Nginx
- 點選回車實現按鈕點選功能
- Android 實現切換主題皮膚功能(類似於眾多app中的 夜間模式,主題包等)AndroidAPP模式
- 基於Linux的mysql主從配置LinuxMySql
- 基於 Docker 的 MongoDB 主從叢集DockerMongoDB
- Memcached實戰之複製----基於repcached的主從【轉】PCA
- 技術分享| 基於 Etcd 的分散式鎖實現原理及方案分散式
- 搭建PowerDNS+LAP+NFS+MySQL主從半節點同步實現LAMP架構DNSNFSMySqlLAMP架構