基於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)
}
}
}
}
}
相關文章
- Etcd叢集的介紹和選主應用
- 架構設計|基於 raft-listener 實現實時同步的主備叢集架構Raft
- 基於KubeEdge的邊緣節點分組管理設計與實現
- Etcd 使用場景:通過分散式鎖思路實現自動選主分散式
- 基於MySql主從分離的程式碼層實現MySql
- 簡述 zookeeper 基於 Zab 協議實現選主及事務提交協議
- Android主介面連續兩次點選物理返回鍵退出應用功能實現Android
- Golang 基於單節點 Redis 實現的分散式鎖GolangRedis分散式
- redis cluster 故障後,主從位於不同節點的修復。Redis
- 使用Keepalived實現Nginx的雙機主備高可用Nginx
- 基於Masstransit實現Eventbus的功能
- 基於.NetCore開發部落格專案 StarBlog - (14) 實現主題切換功能NetCore
- ZooKeeper系列(3)--基於ZooKeeper實現主從協作
- 使用Redis分散式鎖實現主備Redis分散式
- 主備都是全新的恢復,主主搭建步驟
- mysql主從和主備的區別MySql
- 基於Linux的mysql主從配置LinuxMySql
- mongodb主從仲裁節點配置MongoDB
- DM8 配置DMDSC主備環境(rac到單節點 )
- 基於SpringBoot如何實現一個點贊功能?Spring Boot
- 技術分享| 基於 Etcd 的分散式鎖實現原理及方案分散式
- C# 實現Ping遠端主機功能C#
- 基於Linux的docker mysql主從搭建LinuxDockerMySql
- 基於 Docker 的 MongoDB 主從叢集DockerMongoDB
- Memcached實戰之複製----基於repcached的主從【轉】PCA
- zabbix5.0升級6.0,實現原生主備的同時實現高可用
- kafkaer:基於模板的 Kafka 主題/叢集/ACL 管理自動化Kafka
- 基於Fixed定位的框選功能
- 搭建PowerDNS+LAP+NFS+MySQL主從半節點同步實現LAMP架構DNSNFSMySqlLAMP架構
- 部署otter實現mysql主備資料同步(下)MySql
- 部署otter實現mysql主備資料同步(上)MySql
- 4.2.13 主備庫實現自動故障轉移
- Postgrsql 從節點當機,主節點執行DML語句出現等待情況SQL
- jQuery實現簡單點選隱藏和點選顯示列表的功能jQuery
- KPN當選NEO主網共識節點,加速去中心化程式中心化
- 基於js實現點選按鈕回到頂部JS
- 基於 Vue 的商品主圖放大鏡方案Vue
- mysql 基於日誌的主從複製MySql