You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 15:43:18