Documentation
¶
Index ¶
- Constants
- type ConnectionManager
- type DsnConnectionManager
- type FixedSqlDBConnectionManager
- type FuncConnectionProvider
- func (x *FuncConnectionProvider[Connection]) Name() string
- func (x *FuncConnectionProvider[Connection]) Return(ctx context.Context, connection Connection) error
- func (x *FuncConnectionProvider[Connection]) SetName(name string) *FuncConnectionProvider[Connection]
- func (x *FuncConnectionProvider[Connection]) SetReturnFunc(returnFunc func(ctx context.Context, connection Connection) error) *FuncConnectionProvider[Connection]
- func (x *FuncConnectionProvider[Connection]) SetShutdownFunc(shutdownFunc func(ctx context.Context) error) *FuncConnectionProvider[Connection]
- func (x *FuncConnectionProvider[Connection]) SetTakeFunc(takeFunc func(ctx context.Context) (Connection, error)) *FuncConnectionProvider[Connection]
- func (x *FuncConnectionProvider[Connection]) Shutdown(ctx context.Context) error
- func (x *FuncConnectionProvider[Connection]) Take(ctx context.Context) (Connection, error)
- type LockInformation
- type SqlRowsIterator
- type Storage
- type TimeProvider
- type Version
Constants ¶
const ( // DefaultStorageDatabaseName 存储引擎未指定数据库名字的时候默认使用的数据库名字 DefaultStorageDatabaseName = "storage_lock" // DefaultStorageTableName 存储引擎未指定用来存储锁的表的名字的时候默认使用的表名字 DefaultStorageTableName = "storage_lock" )
const DSNConnectionManagerName = "dsn-connection-manager"
const FixedSqlDBConnectionManagerName = "fixed-sql-db-connection-manager"
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ConnectionManager ¶
type ConnectionManager[Connection any] interface { // Name 连接提供器的名字,用于区分不同的连接提供器,连接器的名字必须指定不允许为空字符串 Name() string // Take 获取一个往Storage的连接 Take(ctx context.Context) (Connection, error) // Return 使用完毕,把Storage的连接归还,用于在一些从连接池中拿连接使用完毕必须手动释放否则会资源泄露的场景下及时释放资源 Return(ctx context.Context, connection Connection) error // Shutdown 把整个连接管理器关闭掉,彻底不用了,Storage Lock并不会调用这个方法,你应该在你的系统退出的时候调用此方法释放整个连接管理器使用到的资源 Shutdown(ctx context.Context) error }
ConnectionManager 把与Storage的连接的管理抽象为一个组件,属于比较底层的接口,用来适配上层的各种情况 比如上层可以是从DSN直接创建数据库连接,也可以是从一个已经存在的连接池中拿出来连接,甚至从已有的ORM、sqlx、sql.DB中复用连接 或者任何你想扩展的实现,总之它是一个带泛型的接口,你可以根据你的需求发挥想象力任意创造!
type DsnConnectionManager ¶
type DsnConnectionManager struct { // DSN // "root:123456@tcp(127.0.0.1:4000)/test?charset=utf8mb4" DSN string // contains filtered or unexported fields }
DsnConnectionManager 从DSN维持数据库连接,用于只有一个DSN的情况下创建连接管理器
func NewDsnConnectionManager ¶
func NewDsnConnectionManager(driverName, dsn string) *DsnConnectionManager
func (*DsnConnectionManager) Name ¶
func (x *DsnConnectionManager) Name() string
type FixedSqlDBConnectionManager ¶
type FixedSqlDBConnectionManager struct {
// contains filtered or unexported fields
}
FixedSqlDBConnectionManager 每次创建连接都返回固定的 *sql.DB 实例,用于在其他地方已经创建了一个*sql.DB的时候与其共享连接资源 TODO 2023-8-4 01:35:23 单元测试,虽然感觉没啥必要这要都能出错我跑去厕所大吃特吃!
func NewFixedSqlDBConnectionManager ¶
func NewFixedSqlDBConnectionManager(db *sql.DB) *FixedSqlDBConnectionManager
func (*FixedSqlDBConnectionManager) Name ¶
func (x *FixedSqlDBConnectionManager) Name() string
type FuncConnectionProvider ¶
type FuncConnectionProvider[Connection any] struct { // contains filtered or unexported fields }
FuncConnectionProvider 通过一个函数获取连接,这样就不必再单独写一个接口了,不是一个具体的实现,仅仅是为了外部实现简单一些 TODO 2023-8-4 01:38:10 单元测试
func NewFuncConnectionProvider ¶
func NewFuncConnectionProvider[Connection any]() *FuncConnectionProvider[Connection]
func (*FuncConnectionProvider[Connection]) Name ¶
func (x *FuncConnectionProvider[Connection]) Name() string
func (*FuncConnectionProvider[Connection]) Return ¶
func (x *FuncConnectionProvider[Connection]) Return(ctx context.Context, connection Connection) error
func (*FuncConnectionProvider[Connection]) SetName ¶
func (x *FuncConnectionProvider[Connection]) SetName(name string) *FuncConnectionProvider[Connection]
func (*FuncConnectionProvider[Connection]) SetReturnFunc ¶
func (x *FuncConnectionProvider[Connection]) SetReturnFunc(returnFunc func(ctx context.Context, connection Connection) error) *FuncConnectionProvider[Connection]
func (*FuncConnectionProvider[Connection]) SetShutdownFunc ¶
func (x *FuncConnectionProvider[Connection]) SetShutdownFunc(shutdownFunc func(ctx context.Context) error) *FuncConnectionProvider[Connection]
func (*FuncConnectionProvider[Connection]) SetTakeFunc ¶
func (x *FuncConnectionProvider[Connection]) SetTakeFunc(takeFunc func(ctx context.Context) (Connection, error)) *FuncConnectionProvider[Connection]
type LockInformation ¶
type LockInformation struct { // 锁的ID LockId string `json:"lock_id"` // 当前时谁在持有这个锁,是一个全局唯一的ID OwnerId string `json:"owner_id"` // 锁的变更版本号,乐观锁避免CAS的ABA问题 Version Version `json:"version"` // 锁被锁定了几次,是为了支持可重入锁,在释放锁的时候会根据加锁的次数来决定是否真正的释放锁还是就减少一次锁定次数 LockCount int `json:"lock_count"` // 这个锁是从啥时候开始被OwnerId所持有的,用于判断持有锁的时间 LockBeginTime time.Time `json:"lock_begin_time"` // 锁的owner持有此锁的租约过期时间, LeaseExpireTime time.Time `json:"lease_expire_time"` }
LockInformation 锁的相关信息,是要持久化保存到相关介质中的
func LockInformationFromJsonString ¶
func LockInformationFromJsonString(jsonString string) (*LockInformation, error)
LockInformationFromJsonString 从JSON字符串反序列化锁的信息
func (*LockInformation) ToJsonString ¶
func (x *LockInformation) ToJsonString() string
ToJsonString 把当前锁的信息序列化为JSON字符串以便存储到数据库
type SqlRowsIterator ¶
type SqlRowsIterator struct {
// contains filtered or unexported fields
}
SqlRowsIterator 用来把sql.Row包装为一个迭代器
func NewSqlRowsIterator ¶
func NewSqlRowsIterator(rows *sql.Rows) *SqlRowsIterator
func (*SqlRowsIterator) Next ¶
func (x *SqlRowsIterator) Next() bool
func (*SqlRowsIterator) Value ¶
func (x *SqlRowsIterator) Value() *LockInformation
type Storage ¶
type Storage interface { // GetName Storage的名称,用于区分不同的Storage的实现 // Returns: // string: Storage的名字,应该返回一个有辨识度并且简单易懂的名字,名字不能为空,否则认为是不合法的Storage实现 GetName() string // Init 初始化操作,比如创建存储锁的表,需要支持多次调用,每次创建Storage的时候会调用此方法初始化 // Params: // ctx: // Returns: // error: 初始化发生错误时返回对应的错误 Init(ctx context.Context) error // UpdateWithVersion 如果存储的是指定版本的话,则将其更新 // Params: // lockId 表示锁的ID // exceptedValue 仅当老的值为这个时才进行更新 // newValue 更新为的新的值 // Returns: // error: 如果是版本不匹配,则返回错误 ErrVersionMiss,如果是其它类型的错误,依据情况自行返回 UpdateWithVersion(ctx context.Context, lockId string, exceptedVersion, newVersion Version, lockInformation *LockInformation) error // CreateWithVersion 尝试将锁的信息插入到存储介质中,返回是否插入成功,底层存储的时候应该将锁的ID作为唯一ID,不能重复存储 // 也就是说这个方法仅在锁不存在的时候才能执行成功,其它情况应该插入失败返回对应的错误 // Params: // ctx: // lockId: // version: // lockInformation: // Returns: // error: CreateWithVersion(ctx context.Context, lockId string, version Version, lockInformation *LockInformation) error // DeleteWithVersion 如果锁的当前版本是期望的版本,则将其删除 // 如果是版本不匹配,则返回错误 ErrVersionMiss,如果是其它类型的错误,依据情况自行返回 // DeleteWithVersion(ctx context.Context, lockId string, exceptedVersion Version, lockInformation *LockInformation) error // Get 获取锁之前存储的值,如果没有的话则返回空字符串,如果发生了错误则返回对应的错误信息,如果正常返回则是LockInformation的JSON字符串 // Params: // ctx: 用来做超时控制之类的 // lockId: 要查询的锁的ID // Returns: // string: // error: Get(ctx context.Context, lockId string) (string, error) // TimeProvider 分布式锁的话时间必须使用统一的时间,这个时间推荐是以Storage的时间为准,Storage要能够提供时间查询的功能 // 这是因为分布式锁的算法需要根据时间来协调推进,而当时间不准确的时候算法可能会失效从而导致锁失效 // TODO 2023-5-15 01:48:19 基于实例的时间在分布式数据库中可能会失效,单实例没问题 // TODO 2023-8-3 21:53:35 在文档中用实际例子演示分布式情况下可能会存在的问题 // Params: // ctx: 用来做超时控制之类的 // Returns: // time.Time: 返回Storage的当前时间 // error: 获取时间失败时则返回对应的错误 TimeProvider // Close 关闭此存储介质,一般在系统退出释放资源的时候调用一下 // Params: // ctx: 用来做超时控制之类的 // Returns: // error: 如果关闭失败,则返回对应的错误 Close(ctx context.Context) error // List 列出当前的Storage所持有的所有的锁的信息,因为数量可能会比较多,所以这里使用了一个迭代器模式 // 虽然实际上可能用channel会更Golang一些,但是迭代器会比较易于实现并能够绑定一些内置的方法便于操作 // Params: // ctx: 用来做超时控制之类的 // Returns: // iterator.Iterator[*LockInformation]: 迭代器用来承载当前所有的锁 // error: 如果列出失败,则返回对应类型的错误 List(ctx context.Context) (iterator.Iterator[*LockInformation], error) }
Storage 表示一个存储介质的实现,要实现四个增删改查的方法和一个初始化的方法,以及能够提供Storage的日期, 因为在分布式系统中日期很重要,必须保证参与分布式运算的各个节点使用相同的时间
type TimeProvider ¶
TimeProvider 能够提供时间的时间源,可以从数据库读取,也可以从NTP服务器上读取,只要能够返回一个准确的时间即可(其实不准确也可以,只要是统一的,一直往前的,不会出现时钟回拨的)