zvvq技术分享网

golang框架如何实现分布式锁?(redis分布式锁的使

作者:zvvq博客网
导读在 go 框架中,实现分布式锁有以下两种方法:etcd:利用 etcd 的 watch 特性,当锁被释放时触发事件通知,实现分布式锁。 redis :使用 redis 的 setnx 和 expire 命令,实现简单可靠的分布式

在 go 框架中,完成分布式锁有以下两种方式:etcd:运用 etcd 的 watch 特点,当锁被释放时触发事件通告,完成分布式锁。redis:应用 redis 的 setnx 和 expire 指令,完成简易可靠的分布式锁。

zvvq.cn

内容来自samhan

Go 架构完成分布式锁在分布式系统中,需要确保不同服务或过程访问共享资源时顺序浏览,此时就需要应用分布式锁。在 Go 框架中,几个流行的库能够实现分布式锁,如分布式融洽服务 Etcd 和分布式 KV 数据库 Redis。

内容来自zvvq

EtcdEtcd 是一个分布式、高可用的键值存放,适合于完成分布式锁。Etcd 的锁机制通过运用其 Watch 特点,当锁被释放时触发事件通告。

zvvq好,好zvvq

//import"github.com/coreos/etcd/clientv3" copyright zvvq

//EtcdLock完成了分布式锁 本文来自zvvq

type EtcdLock struct { 本文来自zvvq

client clientv3.Client 内容来自zvvq,别采集哟

key string

copyright zvvq

}

copyright zvvq

// NewEtcdLock 创建一个EtcdLock zvvq.cn

func NewEtcdLock(client clientv3.Client, key string) EtcdLock {

本文来自zvvq

return &EtcdLock{

zvvq.cn

client: client,

内容来自zvvq

key: key, 内容来自zvvq

}

内容来自zvvq

}

本文来自zvvq

// Lock 试着获得锁

内容来自zvvq

func (l EtcdLock) Lock() error {

本文来自zvvq

ctx := context.Background()

内容来自samhan666

lease, err := l.client.Grant(ctx, 10) // 租期时间为10秒 内容来自zvvq

if err != nil {

copyright zvvq

return err

本文来自zvvq

} 内容来自zvvq,别采集哟

txn := l.client.Txn(ctx).If(

本文来自zvvq

clientv3.Compare(clientv3.Value(l.key), "=", ""),

zvvq

).Then(

copyright zvvq

clientv3.OpPut(l.key, "locked", clientv3.WithLease(lease.ID)), copyright zvvq

) zvvq.cn

resp, err := txn.Commit() 内容来自zvvq

if err != nil { zvvq

return err

copyright zvvq

}

zvvq.cn

if resp.Succeeded { 内容来自samhan666

return nil

内容来自zvvq,别采集哟

}

内容来自zvvq,别采集哟

return errors.New("获得锁失败")

内容来自samhan666

} zvvq好,好zvvq

// Unlock 释放锁

内容来自samhan

func (l EtcdLock) Unlock() error { 内容来自zvvq

ctx := context.Background()

内容来自zvvq

_, err := l.client.Delete(ctx, l.key)

内容来自zvvq,别采集哟

return err 内容来自zvvq,别采集哟

}

内容来自samhan

RedisRedis 是一种分布式 KV 数据库,还支持分布式锁的完成。Redis 带来了 SETNX 和 EXPIRE 指令,可用于完成简易可靠的锁。 zvvq好,好zvvq

//import"github.com/go-redis/redis/v8" 本文来自zvvq

// RedisLock完成了分布式锁 内容来自zvvq

type RedisLockstruct{ copyright zvvq

clientredis.Client 内容来自zvvq,别采集哟

keystring zvvq好,好zvvq

}

本文来自zvvq

//NewRedisLock创建一个RedisLock 本文来自zvvq

func NewRedisLock(client redis.Client, key string) RedisLock { copyright zvvq

return &RedisLock{ 内容来自zvvq

client: client,

zvvq

key: key,

内容来自zvvq

}

zvvq

} 本文来自zvvq

// Lock 试着获得锁 zvvq好,好zvvq

func (l RedisLock) Lock() error { zvvq

ctx := context.Background()

zvvq

res, err := l.client.SetNX(ctx, l.key, "locked", 10time.Second).Result() // 锁10秒 内容来自samhan666

if err != nil {

zvvq

return err

内容来自samhan666

} zvvq

if !res {

内容来自zvvq,别采集哟

return errors.New("获得锁失败")

zvvq

} zvvq

return nil

内容来自samhan666

}

copyright zvvq

// Unlock 释放锁 内容来自zvvq

func (l RedisLock) Unlock() error { 内容来自zvvq,别采集哟

ctx := context.Background() copyright zvvq

_, err := l.client.Del(ctx, l.key).Result() zvvq好,好zvvq

return err

内容来自zvvq,别采集哟

} 内容来自samhan666

实战案例考虑一个场景,多个微服务共享一个数据库连接池,为了避免并发浏览造成数据库连接被耗光,必须对连接池开展分布式锁操纵。

内容来自zvvq

lock:=NewEtcdLock(client,"db-pool-lock")

内容来自samhan

iferr:=lock.Lock();err!=nil{ 内容来自zvvq

log.Fatalf("获得锁失败: %v", err) 内容来自zvvq

} 内容来自samhan666

// 浏览数据库连接池...

内容来自samhan

if err := lock.Unlock(); err != nil { 本文来自zvvq

log.Fatalf("释放锁失败: %v", err)

内容来自zvvq

}

zvvq.cn

以上就是golang架构如何做到分布式锁?的详细内容,大量请关注其他类似文章! 内容来自samhan666