golang基于MySQL实现分布式锁插件库go-mysql-lock的使用
golang基于MySQL实现分布式锁插件库go-mysql-lock的使用
go-mysql-lock提供了基于MySQL的GET_LOCK函数的锁原语。锁名称是字符串,MySQL强制锁名称的最大长度为64个字符。
使用场景
虽然Zookeeper和etcd等系统提供了成熟的锁原语,但当你的应用程序主要依赖MySQL的正常运行和健康时,这些系统增加的弹性并没有带来太多好处。go-mysql-lock在你有多个应用程序实例且这些实例都依赖同一个MySQL实例时很有用,你希望这些应用程序实例中只有一个能持有锁并执行某些任务。
安装
go get github.com/sanketplus/go-mysql-lock
示例
package main
import (
"context"
"database/sql"
_ "github.com/go-sql-driver/mysql"
"github.com/sanketplus/go-mysql-lock"
)
func main() {
// 连接MySQL数据库
db, _ := sql.Open("mysql", "root@tcp(localhost:3306)/dyno_test")
// 创建锁实例
locker := gomysqllock.NewMysqlLocker(db)
// 获取锁
lock, _ := locker.Obtain("foo")
// 释放锁
lock.Release()
}
特性
可定制的刷新周期
一旦获得锁,一个goroutine会定期(默认每秒)在连接上执行ping操作,因为锁在连接(会话)上是有效的。可以配置刷新间隔:
locker := gomysqllock.NewMysqlLocker(db, gomysqllock.WithRefreshInterval(time.Millisecond*500))
使用上下文获取锁
默认情况下,获取锁的尝试是由后台上下文支持的。这意味着Obtain
调用将无限期阻塞。可以选择使用用户给定的上下文进行Obtain
调用,该上下文将与给定的上下文一起取消。
以下调用将在1秒后放弃,如果没有获得锁:
locker := gomysqllock.NewMysqlLocker(db)
ctxShort, _ := context.WithDeadline(context.Background(), time.Now().Add(time.Second))
lock, err := locker.ObtainContext(ctxShort, "key")
使用(MySQL)超时获取锁
MySQL能够在给定的秒数内超时并返回,如果锁不能被获取。在使用ObtainTimeout
和ObtainTimeoutContext
时可以指定这个超时。超时时,返回ErrMySQLTimeout
,并且没有获得锁。
以下调用将在1秒后放弃,如果没有获得锁,使用MySQL超时选项:
locker := gomysqllock.NewMysqlLocker(db)
lock, err := locker.ObtainTimeout("key", 1)
知道锁何时丢失
获取的锁有一个上下文,如果锁丢失,该上下文将被取消。这是在一个goroutine不断ping连接时确定的。如果在ping时出现错误,假设连接有错误,上下文将被取消。锁的所有者会收到锁丢失的通知。
context := lock.GetContext()
兼容性
这个库已经针对MySQL 8和MariaDB 10.1进行了测试(自动),它应该适用于MariaDB版本>=10.1,MySQL版本>=5.6,以及Vitess版本>=15.0。
注意,在MariaDB 10.1/MySQL 5.6及更早版本上,GET_LOCK
函数不会无限期锁定,因为这些版本不接受0或负值的超时。这意味着在MySQL <=5.6/MariaDB <=10.1中,你不能使用Obtain
或ObtainContext
。为了实现类似的目标,你可以使用ObtainTimeout
(和ObtainTimeoutContext
)并使用非常高的超时值。
更多关于golang基于MySQL实现分布式锁插件库go-mysql-lock的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html