locker

package
v1.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 28, 2026 License: MIT Imports: 6 Imported by: 0

README

分布式锁之所以难是因为跟网络相关

  1. 网络抖动
  2. 需要单独服务(需要考虑高可用,性能高,通用性的问题)
  3. 加锁解锁需要额外的判断

分布式锁

  1. 如果这个key创建成功则代表锁争抢成功,需要设置过期时间避免程序挂了无解锁导致锁一直存在
  2. 解锁时需要判断这个锁是不是自己加的,此时通过value的值是不是自己的的表示

redis处理细节

  1. 需要使用原子性操作的语句,当不提供时需要使用lua脚本进行处理
  2. 由于go语言是强类型语言,所以尽可能写lua脚本时返回的类型是相同的,避免类型断言

redis及etcd对比

redis可能存在的问题

  • 过期时间 (etcd使用lease,可以对session中的lease续约的方式出来,当逻辑退出session就会销毁就不会续约)
    1. 过期时间不加会导致锁无法释放
    2. 过期时间过短可能导致业务还没处理完就释放导致其他锁抢到
  • 删除key (etcd有版本号等其他字段可以判断)
    • 需要判断这个key是不是自己的通常使用val校验(需要使用原子操作命令或使用lua脚本)
  • 脑裂 & leader退出 (etcd使用的是raft多半认同所以无需leader,写入时多半认可即为真)
    • 在网络分区故障导致无法通讯可能同时有多个leader
    • 由于redis是异步同步,当数据写入leader后宕机退出还没同步到从节点时,从节点成为leader,此时数据丢失
  • redLock
    • 虽然有提供更加完善的锁机制,但是会使用更加复杂

redis为什么依旧使用的那么多

  • 简单
  • 业务中一般已经存在了redis中间件可以继续使用
  • 对锁的要求不是很高(如使用redis消息队列一样,要求高需要替换kafka或rocketMQ)

etcd的优势

  • 使用了raft会对锁的要求更高,但是消耗的时间可能会更高
  • 本身带了版本号等其他额外信息,可以做更多的逻辑判断(etcd库也内置扩展了很多包已经实现对应功能)
  • etcd由于是分布式部署,在稳定性及高可用上会比redis更好
  • 支持事务(IF 语句、Then 语句、Else 语句组成,支持比较 key 的是修改版本号 mod_revision 和创建版本号 create_revision)
  • 支持watch监听机制
  • 使用lease机制进行心跳检查

redis及etcd还能用在什么地方

redis

  • 缓存
  • 分布式锁
  • 消息队列
  • 配置中心(无watch)

etcd (CP 保障数据一致性,牺牲可用性 与zookeeper一样)

  • 服务注册与发现(无提供DNS方式获取、多种机制健康检查)
  • 配置中心
  • 分布式锁
  • leader选举

consul,zookeeper及etcd

consul (gossip协议)

  • 服务注册与发现(提供DNS方式获取、多种机制健康检查)

zookeeper (Zab协议)

  • java系使用——配置中心/锁

etcd (Raft协议)

  • go系使用——配置中心/锁

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrorIsExists       = errors.New("error  is exists")
	ErrorIdentification = errors.New("this identification is error")
	ErrorOverRetry      = errors.New("error over retry")
)

Functions

This section is empty.

Types

type Locker

type Locker interface {
	Lock(ctx context.Context) error
	UnLock(ctx context.Context) error
	Refresh(ctx context.Context) error
	AutoRefresh(ctx context.Context) error
	io.Closer
}

func NewEtcdLocker

func NewEtcdLocker(client *etcdClient.Client, key string) Locker

func NewRedisLocker

func NewRedisLocker(client Store, key, identification string, RefreshTime time.Duration) Locker

type Store

type Store interface {
	SetNX(ctx context.Context, key string, value string, expiration time.Duration) (bool, error)
	Eval(ctx context.Context, script string, keys []string, args ...interface{}) (interface{}, error)
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL