golang分布式锁怎么用
时间: 2023-09-20 11:10:24 浏览: 44
在 Golang 中使用分布式锁可以通过使用第三方库来实现,比如 etcd、consul 等。以下使用 etcd 举例:
1. 安装 etcd:
```
$ go get go.etcd.io/etcd
```
2. 引入 etcdv3 的客户端:
```go
import (
"context"
"go.etcd.io/etcd/clientv3"
)
```
3. 创建 etcdv3 的客户端:
```go
func NewClient() (*clientv3.Client, error) {
config := clientv3.Config{
Endpoints: []string{"http://localhost:2379"}, // etcd 地址
}
return clientv3.New(config)
}
```
4. 获取分布式锁:
```go
func GetLock(client *clientv3.Client, key string) (*clientv3.LeaseKeepAliveResponse, error) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
// 1. 创建租约
leaseResp, err := client.Grant(ctx, 10)
if err != nil {
return nil, err
}
// 2. 创建事务
txn := client.Txn(ctx)
lockKey := fmt.Sprintf("/lock/%s", key)
// 3. 事务操作
txn.If(clientv3.Compare(clientv3.CreateRevision(lockKey), "=", 0)).
Then(clientv3.OpPut(lockKey, "", clientv3.WithLease(leaseResp.ID))).
Else(clientv3.OpGet(lockKey))
// 4. 提交事务
txnResp, err := txn.Commit()
if err != nil {
return nil, err
}
// 5. 获取锁状态
if !txnResp.Succeeded {
return nil, errors.New("get lock failed")
}
// 6. 续约
keepAliveResp, err := client.KeepAlive(ctx, leaseResp.ID)
if err != nil {
return nil, err
}
return keepAliveResp, nil
}
```
5. 释放分布式锁:
```go
func ReleaseLock(client *clientv3.Client, key string, keepAliveResp *clientv3.LeaseKeepAliveResponse) error {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
lockKey := fmt.Sprintf("/lock/%s", key)
// 关闭续约
if _, err := client.Revoke(ctx, keepAliveResp.ID); err != nil {
return err
}
// 删除锁
_, err := client.Delete(ctx, lockKey)
if err != nil {
return err
}
return nil
}
```
使用时可以按照以下方式调用:
```go
func main() {
client, err := NewClient()
if err != nil {
panic(err)
}
defer client.Close()
// 获取锁
keepAliveResp, err := GetLock(client, "mylock")
if err != nil {
panic(err)
}
// 执行业务逻辑
// ...
// 释放锁
if err := ReleaseLock(client, "mylock", keepAliveResp); err != nil {
panic(err)
}
}
```
以上代码仅供参考,具体实现可以根据实际情况进行调整和优化。