您好,登錄后才能下訂單哦!
這篇文章給大家介紹etcd租約機(jī)制及自動(dòng)過(guò)期的實(shí)例分析,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。
對(duì)于實(shí)現(xiàn)分布式樂(lè)觀鎖非常重要。如果鎖了,突然宕機(jī)了,鎖是需要自動(dòng)釋放的。所以這鎖在etcd里是需要生命期的。
過(guò)期演示:
package main import ( "context" "fmt" "go.etcd.io/etcd/clientv3" "time" ) func main() { var ( config clientv3.Config client *clientv3.Client err error lease clientv3.Lease leaseGrantResp *clientv3.LeaseGrantResponse leaseId clientv3.LeaseID putResp *clientv3.PutResponse kv clientv3.KV getResp *clientv3.GetResponse ) //客戶端配置 config = clientv3.Config{ Endpoints: []string{"0.0.0.0:2379"}, //集群列表 DialTimeout: 5 * time.Second, } //建立客戶端 if client, err = clientv3.New(config); err != nil { fmt.Println(err) return } //申請(qǐng)一個(gè)lease(租約) lease = clientv3.NewLease(client) //申請(qǐng)一個(gè)5秒的租約 if leaseGrantResp, err = lease.Grant(context.TODO(), 5); err != nil { fmt.Println(err) return } //拿到租約的id leaseId = leaseGrantResp.ID //獲得kv api子集 kv = clientv3.NewKV(client) //put一個(gè)kv,讓它與租約關(guān)聯(lián)起來(lái),從而實(shí)現(xiàn)10秒后自動(dòng)過(guò)期 if putResp, err = kv.Put(context.TODO(), "/cron/lock/job1", "", clientv3.WithLease(leaseId)); err != nil { fmt.Println(err) return } fmt.Println("寫入成功:", putResp.Header.Revision) //定時(shí)看key過(guò)期沒(méi) for { if getResp, err = kv.Get(context.TODO(), "/cron/lock/job1"); err != nil { fmt.Println(err) return } if getResp.Count == 0 { fmt.Println("kv過(guò)期了") break } fmt.Println("還沒(méi)過(guò)期:", getResp.Kvs) time.Sleep(time.Second) } }
[root@bogon etcd]# go run demo6.go
寫入成功: 27
還沒(méi)過(guò)期: [key:"/cron/lock/job1" create_revision:27 mod_revision:27 version:1 lease:7587837741646622005 ]
還沒(méi)過(guò)期: [key:"/cron/lock/job1" create_revision:27 mod_revision:27 version:1 lease:7587837741646622005 ]
還沒(méi)過(guò)期: [key:"/cron/lock/job1" create_revision:27 mod_revision:27 version:1 lease:7587837741646622005 ]
還沒(méi)過(guò)期: [key:"/cron/lock/job1" create_revision:27 mod_revision:27 version:1 lease:7587837741646622005 ]
還沒(méi)過(guò)期: [key:"/cron/lock/job1" create_revision:27 mod_revision:27 version:1 lease:7587837741646622005 ]
還沒(méi)過(guò)期: [key:"/cron/lock/job1" create_revision:27 mod_revision:27 version:1 lease:7587837741646622005 ]
kv過(guò)期了
[root@bogon etcd]#
申請(qǐng)一把分布式鎖的時(shí)候,是誰(shuí)搶到了key就是搶到了鎖,如果不主動(dòng)釋放這鎖,按道理講不應(yīng)該讓租約過(guò)期,租約過(guò)期主要是為了程序宕掉之后,鎖自動(dòng)釋放,防止程序異常退出。如果程序搶到了這個(gè)鎖,我們希望鎖一直不失效,知道我們主動(dòng)釋放它:
package main import ( "context" "fmt" "go.etcd.io/etcd/clientv3" "time" ) func main() { var ( config clientv3.Config client *clientv3.Client err error lease clientv3.Lease leaseGrantResp *clientv3.LeaseGrantResponse leaseId clientv3.LeaseID putResp *clientv3.PutResponse kv clientv3.KV getResp *clientv3.GetResponse keepResp *clientv3.LeaseKeepAliveResponse keepRespChan <-chan *clientv3.LeaseKeepAliveResponse //只讀channel ) //客戶端配置 config = clientv3.Config{ Endpoints: []string{"0.0.0.0:2379"}, //集群列表 DialTimeout: 5 * time.Second, } //建立客戶端 if client, err = clientv3.New(config); err != nil { fmt.Println(err) return } //申請(qǐng)一個(gè)lease(租約) lease = clientv3.NewLease(client) //申請(qǐng)一個(gè)5秒的租約 if leaseGrantResp, err = lease.Grant(context.TODO(), 5); err != nil { fmt.Println(err) return } //拿到租約的id leaseId = leaseGrantResp.ID //(自動(dòng)續(xù)租)當(dāng)我們申請(qǐng)了租約之后,我們就可以啟動(dòng)一個(gè)續(xù)租 if keepRespChan, err = lease.KeepAlive(context.TODO(), leaseId); err != nil { fmt.Println(err) return } //處理續(xù)租應(yīng)答的協(xié)程 go func() { for { select { case keepResp = <-keepRespChan: if keepRespChan == nil { fmt.Println("租約已經(jīng)失效") goto END } else { //每秒會(huì)續(xù)租一次,所以就會(huì)受到一次應(yīng)答 fmt.Println("收到自動(dòng)續(xù)租應(yīng)答:", keepResp.ID) } } } END: }() //獲得kv api子集 kv = clientv3.NewKV(client) //put一個(gè)kv,讓它與租約關(guān)聯(lián)起來(lái),從而實(shí)現(xiàn)10秒后自動(dòng)過(guò)期 if putResp, err = kv.Put(context.TODO(), "/cron/lock/job1", "", clientv3.WithLease(leaseId)); err != nil { fmt.Println(err) return } fmt.Println("寫入成功:", putResp.Header.Revision) //定時(shí)看key過(guò)期沒(méi) for { if getResp, err = kv.Get(context.TODO(), "/cron/lock/job1"); err != nil { fmt.Println(err) return } if getResp.Count == 0 { fmt.Println("kv過(guò)期了") break } fmt.Println("還沒(méi)過(guò)期:", getResp.Kvs) time.Sleep(time.Second) } }
[root@bogon etcd]# go run demo7.go
寫入成功: 30
收到自動(dòng)續(xù)租應(yīng)答: 7587837741646622039
還沒(méi)過(guò)期: [key:"/cron/lock/job1" create_revision:29 mod_revision:30 version:2 lease:7587837741646622039 ]
還沒(méi)過(guò)期: [key:"/cron/lock/job1" create_revision:29 mod_revision:30 version:2 lease:7587837741646622039 ]
收到自動(dòng)續(xù)租應(yīng)答: 7587837741646622039
還沒(méi)過(guò)期: [key:"/cron/lock/job1" create_revision:29 mod_revision:30 version:2 lease:7587837741646622039 ]
還沒(méi)過(guò)期: [key:"/cron/lock/job1" create_revision:29 mod_revision:30 version:2 lease:7587837741646622039 ]
還沒(méi)過(guò)期: [key:"/cron/lock/job1" create_revision:29 mod_revision:30 version:2 lease:7587837741646622039 ]
收到自動(dòng)續(xù)租應(yīng)答: 7587837741646622039
還沒(méi)過(guò)期: [key:"/cron/lock/job1" create_revision:29 mod_revision:30 version:2 lease:7587837741646622039 ]
還沒(méi)過(guò)期: [key:"/cron/lock/job1" create_revision:29 mod_revision:30 version:2 lease:7587837741646622039 ]
收到自動(dòng)續(xù)租應(yīng)答: 7587837741646622039
......
關(guān)于etcd租約機(jī)制及自動(dòng)過(guò)期的實(shí)例分析就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。