成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

一篇帶給你etcd與分布式鎖

開發(fā) 前端 分布式
可以提供分布式鎖功能的組件有多種,但是每一種都有自己的脾氣與性格。至于選擇哪一種組件,則要看數(shù)據(jù)對(duì)業(yè)務(wù)的重要性,數(shù)據(jù)要求強(qiáng)一致性推薦支持CP的etcd、zookeeper,數(shù)據(jù)允許少量丟失、不要求強(qiáng)一致性的推薦支持AP的Redis。

[[400328]]

1. 實(shí)現(xiàn)分布式鎖的組件們

在分布式系統(tǒng)中,常用于實(shí)現(xiàn)分布式鎖的組件有:Redis、zookeeper、etcd,下面針對(duì)各自的特性進(jìn)行對(duì)比:

由上圖可以看出三種組件各自的特點(diǎn),其中對(duì)于分布式鎖來(lái)說(shuō)至關(guān)重要的一點(diǎn)是要求CP。但是,Redis集群卻不支持CP,而是支持AP。雖然,官方也給出了redlock的方案,但由于需要部署多個(gè)實(shí)例(超過(guò)一半實(shí)例成功才視為成功),部署、維護(hù)比較復(fù)雜。所以在對(duì)一致性要求很高的業(yè)務(wù)場(chǎng)景下(電商、銀行支付),一般選擇使用zookeeper或者etcd。對(duì)比zookeeper與etcd,如果考慮性能、并發(fā)量、維護(hù)成本來(lái)看。由于etcd是用Go語(yǔ)言開發(fā),直接編譯為二進(jìn)制可執(zhí)行文件,并不依賴其他任何東西,則更具有優(yōu)勢(shì)。本文,則選擇etcd來(lái)討論某些觀點(diǎn)。

2. 對(duì)于分布式鎖來(lái)說(shuō)AP為什么不好

在CAP理論中,由于分布式系統(tǒng)中多節(jié)點(diǎn)通信不可避免出現(xiàn)網(wǎng)絡(luò)延遲、丟包等問(wèn)題一定會(huì)造成網(wǎng)絡(luò)分區(qū),在造成網(wǎng)絡(luò)分區(qū)的情況下,一般有兩個(gè)選擇:CP or AP。

① 選擇AP模型實(shí)現(xiàn)分布式鎖時(shí),client在通過(guò)集群主節(jié)點(diǎn)加鎖成功之后,則立刻會(huì)獲取鎖成功的反饋。此時(shí),在主節(jié)點(diǎn)還沒(méi)來(lái)得及把數(shù)據(jù)同步給從節(jié)點(diǎn)時(shí)發(fā)生down機(jī)的話,系統(tǒng)會(huì)在從節(jié)點(diǎn)中選出一個(gè)節(jié)點(diǎn)作為新的主節(jié)點(diǎn),新的主節(jié)點(diǎn)沒(méi)有老的主節(jié)點(diǎn)對(duì)應(yīng)的鎖數(shù)據(jù),導(dǎo)致其他client可以在新的主節(jié)點(diǎn)上拿到相同的鎖。這個(gè)時(shí)候,就會(huì)導(dǎo)致多個(gè)進(jìn)程/線程/協(xié)程來(lái)操作相同的臨界資源數(shù)據(jù),從而引發(fā)數(shù)據(jù)不一致性等問(wèn)題。

② 選擇CP模型實(shí)現(xiàn)分布式鎖,只有在主節(jié)點(diǎn)把數(shù)據(jù)同步給大于1/2的從節(jié)點(diǎn)之后才被視為加鎖成功。此時(shí),主節(jié)點(diǎn)由于某些原因down機(jī),系統(tǒng)會(huì)在從節(jié)點(diǎn)中選取出來(lái)數(shù)據(jù)比較新的一個(gè)從節(jié)點(diǎn)作為新的主節(jié)點(diǎn),從而避免數(shù)據(jù)丟失等問(wèn)題。

所以,對(duì)于分布式鎖來(lái)說(shuō),在對(duì)數(shù)據(jù)有強(qiáng)一致性要求的場(chǎng)景下,AP模型不是一個(gè)好的選擇。如果可以容忍少量數(shù)據(jù)丟失,出于維護(hù)成本等因素考慮,AP模型的Redis可優(yōu)先選擇。

3. 分布式鎖的特點(diǎn)以及操作

對(duì)于分布式鎖來(lái)說(shuō),操作的動(dòng)作包含:

  1. 獲取鎖
  2. 釋放鎖
  3. 業(yè)務(wù)處理過(guò)程中過(guò)程中,另起線程/協(xié)程進(jìn)行鎖的續(xù)約

4. 關(guān)于etcd

官方文檔永遠(yuǎn)是最好的學(xué)習(xí)資料,官方介紹etcd如是說(shuō):

  • 分布式系統(tǒng)使用etcd作為配置管理、服務(wù)發(fā)現(xiàn)和協(xié)調(diào)分布式工作的一致鍵值存儲(chǔ)。許多組織使用etcd來(lái)實(shí)現(xiàn)生產(chǎn)系統(tǒng),如容器調(diào)度器、服務(wù)發(fā)現(xiàn)服務(wù)和分布式數(shù)據(jù)存儲(chǔ)。使用etcd的常見分布式模式包括leader選舉、分布式鎖和監(jiān)視機(jī)器活動(dòng)。
  • Distributed systems use etcd as a consistent key-value store for configuration management, service discovery, and coordinating distributed work. Many organizations use etcd to implement production systems such as container schedulers, service discovery services, and distributed data storage. Common distributed patterns using etcd include leader election, distributed locks, and monitoring machine liveness.
  • https://etcd.io/docs/v3.4/learning/why/

分布式鎖僅是etcd可以實(shí)現(xiàn)眾多功能中的一項(xiàng),服務(wù)注冊(cè)與發(fā)現(xiàn)在etcd中用的則會(huì)更多。

官方也對(duì)眾多組件進(jìn)行了對(duì)比,并整理如下:

通過(guò)對(duì)比可以看出各自的特點(diǎn),至于具體選擇哪一款,你心中可能也有了自己的答案。

5. etcd實(shí)現(xiàn)分布式鎖的相關(guān)接口

對(duì)于分布式鎖,主要用到etcd對(duì)應(yīng)的添加、刪除、續(xù)約接口。

  1. // KV:鍵值相關(guān)操作 
  2. type KV interface { 
  3.     // 存放. 
  4.     Put(ctx context.Context, key, val string, opts ...OpOption) (*PutResponse, error) 
  5.     // 獲取. 
  6.     Get(ctx context.Context, key string, opts ...OpOption) (*GetResponse, error) 
  7.     // 刪除. 
  8.     Delete(ctx context.Context, key string, opts ...OpOption) (*DeleteResponse, error) 
  9.     // 壓縮rev指定版本之前的歷史數(shù)據(jù). 
  10.     Compact(ctx context.Context, rev int64, opts ...CompactOption) (*CompactResponse, error) 
  11.     // 通用的操作執(zhí)行命令,可用于操作集合的遍歷。Put/Get/Delete也是基于Do. 
  12.     Do(ctx context.Context, op Op) (OpResponse, error) 
  13.     // 創(chuàng)建一個(gè)事務(wù),只支持If/Then/Else/Commit操作. 
  14.     Txn(ctx context.Context) Txn 
  15.  
  16.  
  17. // Lease:租約相關(guān)操作 
  18. type Lease interface { 
  19.     // 分配一個(gè)租約. 
  20.     Grant(ctx context.Context, ttl int64) (*LeaseGrantResponse, error) 
  21.     // 釋放一個(gè)租約. 
  22.     Revoke(ctx context.Context, id LeaseID) (*LeaseRevokeResponse, error) 
  23.     // 獲取剩余TTL時(shí)間. 
  24.     TimeToLive(ctx context.Context, id LeaseID, opts ...LeaseOption) (*LeaseTimeToLiveResponse, error) 
  25.     // 獲取所有租約. 
  26.     Leases(ctx context.Context) (*LeaseLeasesResponse, error) 
  27.     // 續(xù)約保持激活狀態(tài). 
  28.     KeepAlive(ctx context.Context, id LeaseID) (<-chan *LeaseKeepAliveResponse, error) 
  29.     // 僅續(xù)約激活一次. 
  30.     KeepAliveOnce(ctx context.Context, id LeaseID) (*LeaseKeepAliveResponse, error) 
  31.     // 關(guān)閉續(xù)約激活的功能. 
  32.     Close() error 

 6. etcd實(shí)現(xiàn)分布式鎖代碼示例

  1. package main 
  2.  
  3. import ( 
  4.     "context" 
  5.     "fmt" 
  6.     "go.etcd.io/etcd/clientv3" 
  7.     "time" 
  8.  
  9. var conf clientv3.Config 
  10.  
  11. // 鎖結(jié)構(gòu)體 
  12. type EtcdMutex struct { 
  13.     Ttl int64//租約時(shí)間 
  14.  
  15.     Conf   clientv3.Config    //etcd集群配置 
  16.     Key    string//etcd的key 
  17.     cancel context.CancelFunc //關(guān)閉續(xù)租的func 
  18.  
  19.     txn     clientv3.Txn 
  20.     lease   clientv3.Lease 
  21.     leaseID clientv3.LeaseID 
  22.  
  23. // 初始化鎖 
  24. func (em *EtcdMutex) init() error { 
  25.     var err error 
  26.     var ctx context.Context 
  27.  
  28.     client, err := clientv3.New(em.Conf) 
  29.     if err != nil { 
  30.         return err 
  31.     } 
  32.  
  33.     em.txn = clientv3.NewKV(client).Txn(context.TODO()) 
  34.     em.lease = clientv3.NewLease(client) 
  35.     leaseResp, err := em.lease.Grant(context.TODO(), em.Ttl) 
  36.  
  37.     if err != nil { 
  38.         return err 
  39.     } 
  40.  
  41.     ctx, em.cancel = context.WithCancel(context.TODO()) 
  42.     em.leaseID = leaseResp.ID 
  43.     _, err = em.lease.KeepAlive(ctx, em.leaseID) 
  44.  
  45.     return err 
  46.  
  47. // 獲取鎖 
  48. func (em *EtcdMutex) Lock() error { 
  49.     err := em.init() 
  50.     if err != nil { 
  51.         return err 
  52.     } 
  53.  
  54.     // LOCK 
  55.     em.txn.If(clientv3.Compare(clientv3.CreateRevision(em.Key), "=", 0)). 
  56.         Then(clientv3.OpPut(em.Key"", clientv3.WithLease(em.leaseID))).Else() 
  57.  
  58.     txnResp, err := em.txn.Commit() 
  59.     if err != nil { 
  60.         return err 
  61.     } 
  62.  
  63.     // 判斷txn.if條件是否成立 
  64.     if !txnResp.Succeeded { 
  65.         return fmt.Errorf("搶鎖失敗"
  66.     } 
  67.  
  68.     returnnil 
  69.  
  70. //釋放鎖 
  71. func (em *EtcdMutex) UnLock() { 
  72.     // 租約自動(dòng)過(guò)期,立刻過(guò)期 
  73.     // cancel取消續(xù)租,而revoke則是立即過(guò)期 
  74.     em.cancel() 
  75.     em.lease.Revoke(context.TODO(), em.leaseID) 
  76.  
  77.     fmt.Println("釋放了鎖"
  78.  
  79. // groutine1 
  80. func try2lock1() { 
  81.     eMutex1 := &EtcdMutex{ 
  82.         Conf: conf, 
  83.         Ttl:  10, 
  84.         Key:  "lock"
  85.     } 
  86.  
  87.     err := eMutex1.Lock() 
  88.     if err != nil { 
  89.         fmt.Println("groutine1搶鎖失敗"
  90.         return 
  91.     } 
  92.     defer eMutex1.UnLock() 
  93.  
  94.     fmt.Println("groutine1搶鎖成功"
  95.     time.Sleep(10 * time.Second
  96.  
  97. // groutine2 
  98. func try2lock2() { 
  99.     eMutex2 := &EtcdMutex{ 
  100.         Conf: conf, 
  101.         Ttl:  10, 
  102.         Key:  "lock"
  103.     } 
  104.  
  105.     err := eMutex2.Lock() 
  106.     if err != nil { 
  107.         fmt.Println("groutine2搶鎖失敗"
  108.         return 
  109.     } 
  110.  
  111.     defer eMutex2.UnLock() 
  112.     fmt.Println("groutine2搶鎖成功"
  113.  
  114. // 測(cè)試代碼 
  115. func EtcdRunTester() { 
  116.     conf = clientv3.Config{ 
  117.         Endpoints:   []string{"127.0.0.1:2379"}, 
  118.         DialTimeout: 5 * time.Second
  119.     } 
  120.  
  121.     // 啟動(dòng)兩個(gè)協(xié)程競(jìng)爭(zhēng)鎖 
  122.     go try2lock1() 
  123.     go try2lock2() 
  124.  
  125.     time.Sleep(300 * time.Second

 總結(jié)

可以提供分布式鎖功能的組件有多種,但是每一種都有自己的脾氣與性格。至于選擇哪一種組件,則要看數(shù)據(jù)對(duì)業(yè)務(wù)的重要性,數(shù)據(jù)要求強(qiáng)一致性推薦支持CP的etcd、zookeeper,數(shù)據(jù)允許少量丟失、不要求強(qiáng)一致性的推薦支持AP的Redis。

 

責(zé)任編輯:姜華 來(lái)源: 今日頭條
相關(guān)推薦

2021-07-21 09:48:20

etcd-wal模塊解析數(shù)據(jù)庫(kù)

2021-04-01 10:51:55

MySQL鎖機(jī)制數(shù)據(jù)庫(kù)

2021-06-16 14:44:32

etcd-raftRaftLeader

2021-07-12 06:11:14

SkyWalking 儀表板UI篇

2021-06-21 14:36:46

Vite 前端工程化工具

2021-01-28 08:55:48

Elasticsear數(shù)據(jù)庫(kù)數(shù)據(jù)存儲(chǔ)

2023-03-29 07:45:58

VS編輯區(qū)編程工具

2021-04-14 14:16:58

HttpHttp協(xié)議網(wǎng)絡(luò)協(xié)議

2021-04-08 11:00:56

CountDownLaJava進(jìn)階開發(fā)

2022-03-22 09:09:17

HookReact前端

2021-03-12 09:21:31

MySQL數(shù)據(jù)庫(kù)邏輯架構(gòu)

2022-02-17 08:53:38

ElasticSea集群部署

2022-04-29 14:38:49

class文件結(jié)構(gòu)分析

2024-06-13 08:34:48

2021-10-28 08:51:53

GPIO軟件框架 Linux

2022-02-25 15:50:05

OpenHarmonToggle組件鴻蒙

2023-03-13 09:31:04

2021-05-08 08:36:40

ObjectString前端

2021-04-23 08:59:35

ClickHouse集群搭建數(shù)據(jù)庫(kù)

2021-07-08 07:30:13

Webpack 前端Tree shakin
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 成人在线国产 | 国产精品久久久久久久久久久久久久 | 欧美一级特黄aaa大片在线观看 | 在线观看中文字幕 | 亚洲九色 | 国产精品毛片av一区 | 国产精品视频一区二区三区 | 久久精品国产99国产精品 | 亚州中文字幕 | 国产一区高清 | 免费一级做a爰片久久毛片潮喷 | 亚洲精品3| 欧美国产亚洲一区二区 | 国产福利在线 | 91人人爽 | 中文字幕在线一区二区三区 | 九色视频网站 | 成年人网站免费 | 久久免费大片 | www.伊人.com | 一级片网址| 久久精品亚洲精品国产欧美 | 精品国产乱码久久久久久闺蜜 | 欧美日韩国产一区二区三区不卡 | 日日碰狠狠躁久久躁婷婷 | 国产精品久久久久久久久图文区 | 一区二区三区在线免费观看 | 午夜影院在线观看免费 | 亚洲精品美女视频 | 国产一区二区三区四区区 | 日韩精品极品视频在线观看免费 | 日韩在线观看一区二区三区 | a久久| 国产在线视频一区二区董小宛性色 | 伊人春色在线观看 | 色爱综合网 | 久久精品亚洲成在人线av网址 | 成人免费大片黄在线播放 | 久久精品国产v日韩v亚洲 | 手机看片1 | 青青久在线视频 |