storage_lock

package module
v0.0.5 Latest Latest
Warning

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

Go to latest
Published: Sep 23, 2023 License: MIT Imports: 19 Imported by: 25

README

Storage Lock

一、这是什么

抽象了一套分布式锁的模型定义和算法,可以基于任何存储介质实现分布式锁!只要此存储介质可以被分布式访问即可,比如以数据库为存储介质,以KV为存储介质,以对象存储为存储介质,以任何可读写的服务为存储介质等等。

目前已经可以使用:

  • 暂无

测试中,即将上线:

开发中:

  • FileSystem

  • Redis

  • Oracle

  • SQLite

  • Zookeeper

  • etcd

  • Elasticsearch

二、安装依赖

go get -u github.com/storage-lock/go-storage-lock

三、模型与算法介绍

TODO 2023-8-7 02:04:09

Documentation

Index

Constants

View Source
const (
	ActionLockNotFoundError       = "lock-not-found-error"
	ActionNotLockOwner            = "not-lock-owner"
	ActionGetLockInformationError = "get-lock-information-error"
	ActionTimeout                 = "timeout"
	ActionSleepRetry              = "sleep-retry"
	ActionSleep                   = "Sleep"
	ActionGetLeaseExpireTimeError = "getLeaseExpireTime-error"
)

通用的事件

View Source
const (
	ActionLockBegin   = "StorageLock.Lock.Begin"
	ActionLockFinish  = "StorageLock.Lock.Finish"
	ActionLockSuccess = "StorageLock.Lock.Begin.Success"
	ActionLockError   = "StorageLock.Lock.Begin.Error"

	ActionTryLockBegin = "StorageLock.Lock.Try.Begin"

	ActionLockExists    = "StorageLock.Lock.Exists"
	ActionLockNotExists = "StorageLock.Lock.NotExists"
	ActionLockReleased  = "StorageLock.Lock.Released"
	ActionLockExpired   = "StorageLock.Lock.Expired"
	ActionLockReentry   = "StorageLock.Lock.Reentry"

	ActionLockBusy        = "StorageLock.Lock.Begin.Busy"
	ActionLockVersionMiss = "StorageLock.Lock.VersionMiss"

	ActionLockRollback        = "StorageLock.Lock.Rollback"
	ActionLockRollbackSuccess = "StorageLock.Lock.Rollback.Success"
	ActionLockRollbackError   = "StorageLock.Lock.Rollback.Error"
)

获取锁相关的事件

View Source
const (
	ActionUnlock        = "StorageLock.Unlock"
	ActionUnlockFinish  = "StorageLock.Unlock.Finish"
	ActionUnlockSuccess = "StorageLock.Unlock.Success"
	ActionUnlockError   = "StorageLock.Unlock.Error"

	ActionUnlockRelease = "StorageLock.Unlock.Release"
	ActionUnlockReentry = "StorageLock.Unlock.Reentry"

	ActionUnlockVersionMiss = "StorageLock.Unlock.VersionMiss"
)

释放锁相关的事件

View Source
const (
	ActionWatchDogRefresh        = "WatchDog.Refresh"
	ActionWatchDogRefreshBegin   = "WatchDog.Refresh.Begin"
	ActionWatchDogRefreshSuccess = "WatchDog.Refresh.Success"
	ActionWatchDogRefreshError   = "WatchDog.Refresh.Error"

	ActionWatchDogCreate        = "WatchDog.Create"
	ActionWatchDogCreateSuccess = "WatchDog.Create.Success"
	ActionWatchDogCreateError   = "WatchDog.Create.Error"

	ActionWatchDogStart        = "WatchDog.Start"
	ActionWatchDogStartSuccess = "WatchDog.Start.Success"
	ActionWatchDogStartError   = "WatchDog.Start.Error"

	ActionWatchDogStop        = "WatchDog.Stop"
	ActionWatchDogStopSuccess = "WatchDog.Stop.success"
	ActionWatchDogStopError   = "WatchDog.Stop.error"

	ActionWatchDogExit = "WatchDog.Exit"

	ActionWatchDogSetEvent = "WatchDog.SetEvent"
)

看门狗相关的事件

View Source
const (
	PayloadLastVersion         = "lastVersion"
	PayloadVersionMissCount    = "versionMissCount"
	PayloadLockBusyCount       = "lockBusyCount"
	PayloadSleep               = "sleep"
	PayloadRefreshSuccessCount = "refreshSuccessCount"
	PayloadContinueErrorCount  = "continueErrorCount"
)

Payload的名字

View Source
const LockIdPrefix = "storage-lock-id-"

LockIdPrefix 自动生成的锁的ID的前缀,但是不建议使用自动生成的锁ID

View Source
const WatchDogCommonsImplName = "watch-dog-commons-impl"
View Source
const WatchDogFactoryCommonsImplName = "watch-dog-factory-commons-impl"
View Source
const WatchDogIDPrefix = "storage-lock-watch-dog-"

WatchDogIDPrefix 看门狗协程分配的ID

Variables

View Source
var (
	ErrLockIdEmpty          = errors.New("lock id can not empty")
	ErrLeaseExpireAfter     = errors.New("LeaseExpireAfter must > time.Second * 3 ")
	ErrLeaseRefreshInterval = errors.New("LeaseRefreshInterval must < ErrLeaseExpireAfter ")
)

ErrLockIdEmpty 参数相关的参数检查

View Source
var (

	// ErrLockFailed 尝试加锁失败
	ErrLockFailed = errors.New("lock failed")

	// ErrLockBusy 锁在被其它人持有着
	ErrLockBusy = errors.New("lock busy")

	// ErrLockAlreadyExists 锁已经存在,无法继续进行给定操作
	ErrLockAlreadyExists = errors.New("lock already exists")

	// ErrUnlockFailed 锁释放失败,锁是自己的,但由于种种原因释放失败了
	ErrUnlockFailed = errors.New("unlock failed")

	// ErrLockNotFound 要操作的锁不存在,本来无一物,何处染尘埃,无法在不存在的锁上施加操作
	ErrLockNotFound = errors.New("lock not found")

	// ErrLockNotBelongYou 尝试释放不属于自己的锁,一般情况下不应该有这个错误,除非发生了越权操作
	ErrLockNotBelongYou = errors.New("v not belong you")

	// ErrLockRefreshFailed 刷新锁的过期时间时出错
	ErrLockRefreshFailed = errors.New("lock refresh failed")
)
View Source
var (

	// ErrVersionMiss 版本未命中,基于版本操作时比较常见的问题
	ErrVersionMiss = errors.New("compare and set miss")

	// ErrOwnerCanOnlyOne 锁的有拥有者只能有一个,这是尝试给锁指定了多个owner时会返回的错误
	ErrOwnerCanOnlyOne = errors.New("lock owner only one")
)
View Source
var (

	// DefaultLeaseExpireAfter 默认的锁的租约有效时间
	// 这个时间不适合设置太长,如果太长的话可能会导致上次持有锁的owner异常退出时锁不能及时得到释放,导致假性持有的时间过长其它需要锁的人不能及时获取到锁
	// 这个值也不适合设置太短,太短的话可能会导致锁来不及续租就过期了从而导致一个锁同时被多个人同时获取,这就导致锁失去了互斥性
	// 这个值的上限不做约定,但是下限不能小于 3 秒
	DefaultLeaseExpireAfter = time.Minute * 5

	// DefaultLeaseRefreshInterval 默认的租约过期时间刷新间隔,如果并发比较高或者网络不是很好的话可以适当的把这个值调大
	// 需要注意的是这个租约的刷新间隔不能超过 (DefaultLeaseExpireAfter - time.Second)
	DefaultLeaseRefreshInterval = time.Second * 30

	// DefaultVersionMissRetryInterval 版本miss时间隔多久再重试
	DefaultVersionMissRetryInterval = time.Second
)

这里使用了var而不是const,是给用户能够修改全局默认值的机会如果他需要的话

Functions

This section is empty.

Types

type OwnerIdGenerator

type OwnerIdGenerator struct {
	// contains filtered or unexported fields
}

OwnerIdGenerator 可以使用这个工具类来生成全局唯一的OwnerID 1. 要满足全局唯一不重复 2. 可读性尽量好一些

func NewOwnerIdGenerator

func NewOwnerIdGenerator() *OwnerIdGenerator

NewOwnerIdGenerator 创建一个OwnerID生成器

func (*OwnerIdGenerator) GenOwnerId added in v0.0.3

func (x *OwnerIdGenerator) GenOwnerId() string

GenOwnerId 这个方法应该具有幂等性,同一个goroutine应该恒返回同一个ID

type StorageLock

type StorageLock struct {
	// contains filtered or unexported fields
}

StorageLock 基于存储介质的锁模型实现,底层存储介质Storage是可插拔的

func NewStorageLock

func NewStorageLock(storage storage.Storage, lockId string) (*StorageLock, error)

NewStorageLock 指定锁的ID创建锁,其它的选项都使用默认的

func NewStorageLockWithOptions

func NewStorageLockWithOptions(storage storage.Storage, options *StorageLockOptions) (*StorageLock, error)

NewStorageLockWithOptions 创建一个基于存储介质的锁 storage: 锁持久化的存储介质,不同的介质有不同的实现,比如基于Mysql、基于MongoDB options: 创建和维护锁时的相关配置项

func (*StorageLock) Lock

func (x *StorageLock) Lock(ctx context.Context, ownerId string) error

Lock 尝试获取锁 @params:

ctx: 用来控制超时,如果想永远不超时则传入context.Background()
ownerId: 是谁在尝试获取锁,如果不指定的话会为当前协程生成一个默认的ownerId

@returns:

error: 当获取锁的时候发生错误的时候会中断竞争锁并返回错误

func (*StorageLock) UnLock

func (x *StorageLock) UnLock(ctx context.Context, ownerId string) error

UnLock 尝试释放锁,如果释放不成功的话则会返回error ownerId: 是谁在尝试释放锁,操作者应该有唯一的标识

type StorageLockOptions

type StorageLockOptions struct {

	// 创建锁的时候可以指定锁ID,如果指定的话会使用给定的值作为锁的ID,未指定的话则会生成一个默认的ID
	// 要想达到分布式协调资源的效果必须手动指定锁的ID(一般是根据业务场景生成一个ID),自动生成的锁ID仅能用于同一个进程内协调资源
	// 比如要分布式操作一个用户的资源,则可以将这个用户的ID作为锁的ID
	// @see:
	//     ErrLockIdEmpty
	LockId string

	// 获取到锁之后期望的租约有效期,比如获取到锁之后租约有效期五分钟,则五分钟锁只有自己才能操作,在获取成功锁之后会有个协程专门负责刷新租约时间
	// @see:
	//     DefaultLeaseExpireAfter
	//     ErrLeaseExpireAfter
	LeaseExpireAfter time.Duration

	// 租约刷新间隔,当获取锁成功时会有一个协程专门负责续约租约,这个参数就决定它每隔多久发起一次续约操作,这个用来保证不会在锁使用的期间突然过期
	LeaseRefreshInterval time.Duration

	// 用于监听观测锁使用过程中的各种事件,如果需要的话自行设置
	EventListeners []events.Listener

	// 用于创建看门狗
	WatchDogFactory WatchDogFactory

	// 版本未命中时的重试间隔
	VersionMissRetryInterval time.Duration
}

StorageLockOptions 创建存储锁的相关选项

func NewStorageLockOptions

func NewStorageLockOptions() *StorageLockOptions

NewStorageLockOptions 使用默认值创建锁的配置项

func NewStorageLockOptionsWithLockId

func NewStorageLockOptionsWithLockId(lockId string) *StorageLockOptions

NewStorageLockOptionsWithLockId 使用默认值创建配置项,同时指定锁的ID

func (*StorageLockOptions) AddEventListeners added in v0.0.3

func (x *StorageLockOptions) AddEventListeners(eventListener events.Listener) *StorageLockOptions

func (*StorageLockOptions) SetEventListeners added in v0.0.3

func (x *StorageLockOptions) SetEventListeners(eventListeners []events.Listener) *StorageLockOptions

func (*StorageLockOptions) SetLeaseExpireAfter

func (x *StorageLockOptions) SetLeaseExpireAfter(leaseExpireAfter time.Duration) *StorageLockOptions

func (*StorageLockOptions) SetLeaseRefreshInterval

func (x *StorageLockOptions) SetLeaseRefreshInterval(leaseRefreshInterval time.Duration) *StorageLockOptions

func (*StorageLockOptions) SetLockId

func (x *StorageLockOptions) SetLockId(lockId string) *StorageLockOptions

func (*StorageLockOptions) SetVersionMissRetryInterval added in v0.0.3

func (x *StorageLockOptions) SetVersionMissRetryInterval(versionMissRetryInterval time.Duration) *StorageLockOptions

func (*StorageLockOptions) SetWatchDogFactory added in v0.0.3

func (x *StorageLockOptions) SetWatchDogFactory(watchDogFactory WatchDogFactory) *StorageLockOptions

type WatchDog added in v0.0.3

type WatchDog interface {

	// Name 狗狗的品种
	Name() string

	// Start 启动看门狗
	Start(ctx context.Context) error

	// Stop 停止看门狗
	Stop(ctx context.Context) error

	// GetID 获取狗狗的ID
	GetID() string

	// Eventable 为狗狗设置事件
	//SetEvent(e *events.Event)
	events.Eventable
}

WatchDog 看门狗协程,让锁的实现者可以自己提供续租的具体实现来替换掉内置的

type WatchDogCommonsImpl added in v0.0.3

type WatchDogCommonsImpl struct {
	// contains filtered or unexported fields
}

WatchDogCommonsImpl 用于在锁存在期间为锁的租约续期的协程,当前实现是每个锁在持有期间都会配备一个刷新锁的租约时间的协程

func NewWatchDogCommonsImpl added in v0.0.3

func NewWatchDogCommonsImpl(ctx context.Context, e *events.Event, lock *StorageLock, ownerId string) *WatchDogCommonsImpl

NewWatchDogCommonsImpl 创建一只看门狗

func (*WatchDogCommonsImpl) GetID added in v0.0.3

func (x *WatchDogCommonsImpl) GetID() string

func (*WatchDogCommonsImpl) Name added in v0.0.3

func (x *WatchDogCommonsImpl) Name() string

func (*WatchDogCommonsImpl) SetEvent added in v0.0.3

func (x *WatchDogCommonsImpl) SetEvent(e *events.Event)

SetEvent 允许在创建后更改日志源

func (*WatchDogCommonsImpl) Start added in v0.0.3

func (x *WatchDogCommonsImpl) Start(ctx context.Context) error

Start 启动看门狗协程

func (*WatchDogCommonsImpl) Stop added in v0.0.3

Stop 停止续租协程

type WatchDogFactory added in v0.0.3

type WatchDogFactory interface {

	// Name 此工厂是什么品种的狗狗而工作,用于表明工厂的类型
	Name() string

	// NewWatchDog 创建一只看门狗
	// ctx: 控制超时传递上下文之类的
	// e: 新创建的WatchDog如果需要支持事件的话,则保存这个WatchDog的根事件,后面它所触发的事件都是这个事件的子事件
	// lock: 在为哪个锁创建WatchDog,WatchDog可能会用到锁的一些上下文之类的,比如lockId啥的
	// ownerId: 这个WatchDog是为哪个主人而创建,狗狗都是很忠诚的,一只狗狗终生只为一个主人守护他的锁
	NewWatchDog(ctx context.Context, e *events.Event, lock *StorageLock, ownerId string) (WatchDog, error)
}

WatchDogFactory 负责创建看门狗的工厂

type WatchDogFactoryCommonsImpl added in v0.0.3

type WatchDogFactoryCommonsImpl struct {
}

WatchDogFactoryCommonsImpl 默认的WatchDogFactory的实现,当创建锁的时候未指定WatchDogFactory时便会使用此实现

func NewWatchDogFactoryCommonsImpl added in v0.0.3

func NewWatchDogFactoryCommonsImpl() *WatchDogFactoryCommonsImpl

func (*WatchDogFactoryCommonsImpl) Name added in v0.0.3

func (*WatchDogFactoryCommonsImpl) NewWatchDog added in v0.0.3

func (x *WatchDogFactoryCommonsImpl) NewWatchDog(ctx context.Context, e *events.Event, lock *StorageLock, ownerId string) (WatchDog, error)

type WatchDogFactoryFuncWrapper added in v0.0.3

type WatchDogFactoryFuncWrapper struct {
	// contains filtered or unexported fields
}

WatchDogFactoryFuncWrapper 用于不声明struct的情况下创建工厂

func NewWatchDogFactoryFuncWrapper added in v0.0.3

func NewWatchDogFactoryFuncWrapper(name string, newFunc func(ctx context.Context, e *events.Event, lock *StorageLock, ownerId string) (WatchDog, error)) *WatchDogFactoryFuncWrapper

func (*WatchDogFactoryFuncWrapper) Name added in v0.0.3

func (*WatchDogFactoryFuncWrapper) NewWatchDog added in v0.0.3

func (x *WatchDogFactoryFuncWrapper) NewWatchDog(ctx context.Context, e *events.Event, lock *StorageLock, ownerId string) (WatchDog, error)

Directories

Path Synopsis
examples

Jump to

Keyboard shortcuts

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