Laravel LockTimeoutException的Go等价实现:用户API请求串行化方案
Go实现同一用户API请求串行执行(分布式锁方案)
对应你提供的Laravel Cache锁逻辑,以下是Go语言的等价实现,使用github.com/go-redsync/redsync/v4基于Redis实现分布式锁,确保同一用户的创建交易请求串行处理:
依赖安装
go get github.com/go-redsync/redsync/v4 go get github.com/go-redsync/redsync/v4/redis/goredis/v9 go get github.com/redis/go-redis/v9
完整代码示例
package main import ( "context" "errors" "fmt" "time" "github.com/go-redsync/redsync/v4" "github.com/go-redsync/redsync/v4/redis/goredis/v9" goredislib "github.com/redis/go-redis/v9" ) // 自定义错误,对应Laravel的LockTimeoutException var ErrLockTimeout = errors.New("create txn api LockTimeout Exception") // 初始化Redis客户端和redsync实例 func initRedsync() *redsync.Redsync { client := goredislib.NewClient(&goredislib.Options{ Addr: "localhost:6379", // 替换为你的Redis服务地址 }) pool := goredis.NewPool(client) return redsync.New(pool) } func createTxn(ctx context.Context, rs *redsync.Redsync, userID string, amount int) error { // 锁的key,和Laravel逻辑保持一致:create_txn_{user_id}_lock lockKey := fmt.Sprintf("create_txn_%s_lock", userID) // 创建互斥锁实例,锁的有效期设置为30秒(对应Laravel锁的第二个参数) mutex := rs.NewMutex(lockKey, redsync.WithExpiry(30*time.Second)) // 尝试获取锁,最多等待5秒(对应Laravel的block(5)) ctxWithTimeout, cancel := context.WithTimeout(ctx, 5*time.Second) defer cancel() if err := mutex.LockContext(ctxWithTimeout); err != nil { // 获取锁超时,返回自定义错误 return ErrLockTimeout } // 确保锁最终被释放,对应Laravel的finally块 defer func() { if ok, err := mutex.Unlock(); !ok || err != nil { // 可在此添加解锁失败的日志记录 fmt.Printf("Failed to release lock for user %s: %v\n", userID, err) } }() // ------------------------------ // 此处编写创建交易的业务逻辑 fmt.Printf("Processing transaction for user %s, amount: %d\n", userID, amount) // 模拟业务处理耗时 time.Sleep(1 * time.Second) // ------------------------------ return nil } func main() { rs := initRedsync() ctx := context.Background() // 模拟同一用户的三个并发请求 go func() { if err := createTxn(ctx, rs, "user001", 50); err != nil { fmt.Println(err) } }() go func() { if err := createTxn(ctx, rs, "user001", 100); err != nil { fmt.Println(err) } }() go func() { if err := createTxn(ctx, rs, "user001", 10); err != nil { fmt.Println(err) } }() // 等待所有goroutine执行完成 time.Sleep(5 * time.Second) }
关键逻辑说明
- 锁标识:复用Laravel的锁key规则,确保不同用户的锁相互隔离
- 锁有效期:设置30秒防止服务意外退出导致锁长期占用
- 等待超时控制:通过
context.WithTimeout实现最多5秒的锁等待逻辑,超时返回自定义错误 - 锁释放保障:使用
defer确保无论业务逻辑执行结果如何,最终都会尝试释放锁 - 分布式适配:基于Redis的Redlock算法实现,支持多实例部署的Go服务场景,和Laravel使用Redis作为Cache驱动的逻辑对齐
内容的提问来源于stack exchange,提问作者Dinesh
相关产品推荐
相关产品推荐

