日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

etcd 笔记(06)— Client 结构定义、客户端(初始化、KV存储Get、Put、事务 Txn、压缩 Compact、Watch、Lease

發布時間:2023/11/28 生活经验 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 etcd 笔记(06)— Client 结构定义、客户端(初始化、KV存储Get、Put、事务 Txn、压缩 Compact、Watch、Lease 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1. Client 定義

Client 定義如下:

type Client struct {ClusterKVLeaseWatcherAuthMaintenance// 認證的用戶名Username string// 認證的密碼Password string
}

這里顯示的都是可導出的模塊結構字段,代表了客戶端能夠使用的幾大核心模塊,具體功能介紹如下。

  • Cluster:向集群里增加 etcd 服務端節點之類,屬于管理員操作;
  • KV:我們主要使用的功能,即操作 K-V
  • Lease:租約相關操作,比如申請一個 TTL=10 秒的租約;
  • Watcher:觀察訂閱,從而監聽最新的數據變化;
  • Auth:管理 etcd 的用戶和權限,屬于管理員操作;
  • Maintenance:維護 etcd,比如主動遷移 etcdleader 節點,屬于管理員操作;

2. gRPC 服務

etcd v3 的通信基于 gRPCproto文件是定義服務端和客戶端通信接口的標準。包括:

  • 客戶端該傳什么樣的參數
  • 服務端該返回什么參數
  • 客戶端該怎么調用
  • 是阻塞還是非阻塞
  • 是同步還是異步

gRPC 推薦使用 proto3 消息格式,proto3 是原有 Protocol Buffer 2(被稱為 proto2)的升級版本,刪除了一部分特性,優化了對移動設備的支持。

發送到 etcd 服務器的每個 API 請求都是一個 gRPC 遠程過程調用。etcd 中的 RPC 接口定義根據功能分類到服務中。

處理 etcd 鍵值的重要服務包括:

  • KV Service:創建、更新、獲取和刪除鍵值對;
  • Watch Service:監視鍵的更改;
  • Lease Service:實現鍵值對過期,客戶端用來續租、保持心跳;
  • Lock Serviceetcd 提供分布式共享鎖的支持;
  • Election Service:暴露客戶端選舉機制;

3. 請求和響應

3.1 請求

etcd3 中的所有 RPC 都遵循相同的格式。每個 RPC 都有一個函數名,該函數將 NameRequest 作為參數并返回 NameResponse 作為響應。例如,這是 Range RPC 描述:

service KV {Range(RangeRequest) returns (RangeResponse)...
}

3.2 響應頭

etcd API 的所有響應都有一個附加的響應標頭,其中包括響應的集群元數據:

message ResponseHeader {uint64 cluster_id = 1;uint64 member_id = 2;int64 revision = 3;uint64 raft_term = 4;
}

其中:

  • Cluster_ID:產生響應的集群的 ID
  • Member_ID:產生響應的成員的 ID;

應用服務可以通過 Cluster_IDMember_ID 字段來確保當前與之通信的正是預期的那個集群或者成員。

  • Revision:產生響應時鍵值存儲的修訂版本號;

應用服務可以使用修訂號字段來獲得當前鍵值存儲庫最新的修訂號。應用程序指定歷史修訂版以進行查詢,如果希望在請求時知道最新修訂版,此功能特別有用。

  • Raft_Term:產生響應時,成員的 Raft 稱謂。

應用服務可以使用 Raft_Term 來檢測集群何時完成一個新的 leader 選舉。

4. etcd clientv3 客戶端

4.1 初始化

我們根據指定的 etcd 節點,建立客戶端與 etcd 集群的連接:

config := clientv3.Config{Endpoints:[]string{"localhost:2379", "localhost:2379"},DialTimeout: 5 * time.Second,
}
client, err := clientv3.New(config)// etcd clientv3 >= v3.2.10, grpc/grpc-go >= v1.7.3
if client == nil || err == context.DeadlineExceeded {// handle errorsfmt.Println(err)panic("invalid connection!")
}
// 客戶端斷開連接
defer client.Close()

如上的代碼實例化了一個 client,這里需要傳入兩個參數。

  • Endpointsetcd 的多個節點服務地址;

  • DialTimeout:創建 client 的首次連接超時時間,這里傳了 5 秒,如果 5 秒都沒有連接成功就會返回 err。

需要注意的是,一旦 client 創建成功,我們就不用再關心后續底層連接的狀態了,client 內部會重連。

4.2 KV 存儲

KV 對象的實例獲取通過如下的方式:

kv := clientv3.NewKV(client)

KV 接口的具體定義:

type KV interface {Put(ctx context.Context, key, val string, opts ...OpOption) (*PutResponse, error)// 檢索 keysGet(ctx context.Context, key string, opts ...OpOption) (*GetResponse, error)// 刪除 key,可以使用 WithRange(end), [key, end) 的方式Delete(ctx context.Context, key string, opts ...OpOption) (*DeleteResponse, error)// 壓縮給定版本之前的 KV 歷史Compact(ctx context.Context, rev int64, opts ...CompactOption) (*CompactResponse, error)// 指定某種沒有事務的操作Do(ctx context.Context, op Op) (OpResponse, error)// Txn 創建一個事務Txn(ctx context.Context) Txn
}

KV 對象的定義我們可知,它就是一個接口對象,包含以下幾個主要的 KV 操作方法。

4.2.1 Put

Put 的定義如下:

Put(ctx context.Context, key, val string, opts ...OpOption) (*PutResponse, error)

其中的參數

  • ctxContext 包對象,用來跟蹤上下文,比如超時控制;
  • key:存儲對象的 key
  • val:存儲對象的 value
  • opts:可變參數,額外選項;

使用示例:

putResp, err := kv.Put(context.TODO(),"aa", "hello-world!")

4.2.2 Get

Get 的定義如下:

Get(ctx context.Context, key string, opts ...OpOption) (*GetResponse, error)

OpOption 為可選的函數傳參:

  • 傳參為 WithRange(end) 時,Get 將返回 [key,end) 范圍內的鍵;
  • 傳參為 WithFromKey() 時,Get 返回大于或等于 key 的鍵;
  • 當通過 rev> 0 傳遞 WithRev(rev) 時,Get 查詢給定修訂版本的鍵;
  • 如果壓縮了所查找的修訂版本,則返回請求失敗,并顯示 ErrCompacted
  • 傳遞 WithLimit(limit) 時,返回的 key 數量受 limit 限制;
  • 傳參為 WithSort 時,將對鍵進行排序;

對應的使用方法如下:

getResp, err := kv.Get(context.TODO(), "aa")

從上面可以看出,Put 返回 PutResponseGet 返回 GetResponse。注意:不同的 KV 操作對應不同的 Response 結構,定義如下:

type (CompactResponse pb.CompactionResponsePutResponse     pb.PutResponseGetResponse     pb.RangeResponseDeleteResponse  pb.DeleteRangeResponseTxnResponse     pb.TxnResponse
)

下面我們分別來看一看 PutResponseGetResponse 映射的 RangeResponse 結構的定義:

type PutResponse struct {Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`// 請求中如有 prev_kv,響應時也會攜帶 prev_kv PrevKv *mvccpb.KeyValue `protobuf:"bytes,2,opt,name=prev_kv,json=prevKv" json:"prev_kv,omitempty"`
}
//Header 里保存的主要是本次更新的 revision 信息
type RangeResponse struct {Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`// kvs 是一個匹配 range 請求的鍵值對列表Kvs []*mvccpb.KeyValue `protobuf:"bytes,2,rep,name=kvs" json:"kvs,omitempty"`// more 用以分頁 More bool `protobuf:"varint,3,opt,name=more,proto3" json:"more,omitempty"`// count 表示 range 的鍵值對數量Count int64 `protobuf:"varint,4,opt,name=count,proto3" json:"count,omitempty"`
}

Kvs 字段,保存了本次 Get 查詢到的所有 KV 對,我們繼續看一下 mvccpb.KeyValue 對象的定義:

type KeyValue struct {Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`// create_revision 是當前 key 的最后創建版本CreateRevision int64 `protobuf:"varint,2,opt,name=create_revision,json=createRevision,proto3" json:"create_revision,omitempty"`// mod_revision 是指當前 key 的最新修訂版本ModRevision int64 `protobuf:"varint,3,opt,name=mod_revision,json=modRevision,proto3" json:"mod_revision,omitempty"`// key 的版本,每次更新都會增加版本號Version int64 `protobuf:"varint,4,opt,name=version,proto3" json:"version,omitempty"`Value []byte `protobuf:"bytes,5,opt,name=value,proto3" json:"value,omitempty"`// 綁定了 key 的租期 Id,當 lease 為 0 ,則表明沒有綁定 key;租期過期,則會刪除 keyLease int64 `protobuf:"varint,6,opt,name=lease,proto3" json:"lease,omitempty"`
}

至于 RangeResponse.MoreCount,當我們使用 withLimit() 選項進行 Get 時會發揮作用,相當于分頁查詢。

通過一個特別的 Get 選項,獲取 aa 目錄下的所有子目錄:

rangeResp, err := kv.Get(context.TODO(), "/aa", clientv3.WithPrefix())

WithPrefix() 用于查找以 /aa為前綴的所有 key,因此可以模擬出查找子目錄的效果。我們知道 etcd 是一個有序的 KV 存儲,因此 /aa 為前綴的 key 總是順序排列在一起。

WithPrefix 實際上會轉化為范圍查詢,它根據前綴 /aa 生成了一個 key range[“/aa/”, “/aa0”),這是因為比 /大的字符是 0,所以以 /aa0 作為范圍的末尾,就可以掃描到所有的 /aa/ 打頭的 key 了。

4.3 事務 Txn

Txn 方法在單個事務中處理多個請求。Txn 請求增加鍵值存儲的修訂版本,并為每個完成的請求生成帶有相同修訂版本的事件,etcd 不容許在一個 Txn 中多次修改同一個 key。

Txn 接口定義如下:

rpc Txn(TxnRequest) returns (TxnResponse) {}

4.4 Compact

Compact 方法壓縮 etcd 鍵值對存儲中的事件歷史。鍵值對存儲應該定期壓縮,否則事件歷史會無限制地持續增長。

Compact 接口定義如下:

rpc Compact(CompactionRequest) returns (CompactionResponse) {}

請求的消息體是 CompactionRequestCompactionRequest 壓縮鍵值對存儲到給定修訂版本,所有修訂版本比壓縮修訂版本小的鍵都將被刪除。

4.5 Watch

Watch API 提供了一個基于事件的接口,用于異步監視鍵的更改。etcd 監視程序通過給定的修訂版本(當前版本或歷史版本)持續監視 key 更改,并將 key 更新流回客戶端。

rpc.protoWatch Service 定義如下:

service Watch {rpc Watch(stream WatchRequest) returns (stream WatchResponse) {}
}

Watch 觀察將要發生或者已經發生的事件。輸入和輸出都是流,輸入流用于創建和取消觀察,而輸出流發送事件。一個觀察 RPC 可以一次性在多個 key 范圍上觀察,并為多個觀察流化事件。整個事件歷史可以從最后壓縮修訂版本開始觀察。Watch Service 只有一個 Watch 方法。

4.6 Lease Service

Lease Service 提供租約的支持。Lease 是一種檢測客戶端存活狀況的機制。集群授予客戶端具有生存時間的租約。如果 etcd 集群在給定的 TTL 時間內未收到 keepAlive,則租約到期。

為了將租約綁定到鍵值存儲中,每個 key 最多可以附加一個租約。當租約到期或被撤銷時,該租約依附的所有 key 都將被刪除,每個過期的密鑰都會在事件歷史記錄中生成一個刪除事件。

rpc.protoLease Service 定義的接口如下:

service Lease {rpc LeaseGrant(LeaseGrantRequest) returns (LeaseGrantResponse) {}rpc LeaseRevoke(LeaseRevokeRequest) returns (LeaseRevokeResponse) {}rpc LeaseKeepAlive(stream LeaseKeepAliveRequest) returns (stream LeaseKeepAliveResponse) {}rpc LeaseTimeToLive(LeaseTimeToLiveRequest) returns (LeaseTimeToLiveResponse) {}
}

其中:

  • LeaseGrant 創建一個租約;
  • LeaseRevoke 撤銷一個租約;
  • LeaseKeepAlive 用于維持租約;
  • LeaseTimeToLive 獲取租約信息;

4.7 Lock Service

Lock Service 提供分布式共享鎖的支持。Lock ServicegRPC 接口的方式暴露客戶端鎖機制。

v3lock.protoLock Service 定義如下:

service Lock {rpc Lock(LockRequest) returns (LockResponse) {}rpc Unlock(UnlockRequest) returns (UnlockResponse) {}
}

其中:

  • Lock 方法,在給定命令鎖上獲得分布式共享鎖;
  • Unlock 使用 Lock 返回的 key 并釋放對鎖的持有;

參考:
https://kaiwu.lagou.com/course/courseInfo.htm?courseId=613#/detail/pc?id=6403

總結

以上是生活随笔為你收集整理的etcd 笔记(06)— Client 结构定义、客户端(初始化、KV存储Get、Put、事务 Txn、压缩 Compact、Watch、Lease的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。