locker.go 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. package redisclient
  2. import (
  3. "errors"
  4. "fmt"
  5. "github.com/go-redsync/redsync/v4"
  6. "go_server/base/core"
  7. "time"
  8. )
  9. // Lock 获取分布式锁
  10. func Lock(lockKey string) (*redsync.Mutex, error) {
  11. opts := LockOptions{
  12. Expiration: int32(3), // 锁的过期时间(秒)
  13. MaxRetries: 8, // 最大重试次数
  14. RetryDelay: 300 * time.Millisecond, // 重试间隔
  15. }
  16. // 默认值
  17. if opts.Expiration <= 0 {
  18. opts.Expiration = DefaultLockOptions.Expiration
  19. }
  20. if opts.MaxRetries <= 0 {
  21. opts.MaxRetries = DefaultLockOptions.MaxRetries
  22. }
  23. if opts.RetryDelay <= 0 {
  24. opts.RetryDelay = DefaultLockOptions.RetryDelay
  25. }
  26. return LockWithOptions(lockKey, opts)
  27. }
  28. // LockWithOptions 使用指定的选项获取分布式锁
  29. // 返回锁定的 mutex,失败时返回错误
  30. // 使用完后需调用 Unlock() 释放锁
  31. // 获取锁
  32. func LockWithOptions(lockKey string, opts LockOptions) (*redsync.Mutex, error) {
  33. if opts.Expiration <= 0 || opts.MaxRetries < 1 || opts.RetryDelay < 0 {
  34. return nil, errors.New("invalid lock options")
  35. }
  36. mutex := redisSync().NewMutex(
  37. lockKey,
  38. redsync.WithExpiry(time.Duration(opts.Expiration)*time.Second),
  39. redsync.WithTries(opts.MaxRetries),
  40. redsync.WithRetryDelay(opts.RetryDelay),
  41. )
  42. if err := mutex.Lock(); err != nil {
  43. return nil, fmt.Errorf("failed to acquire lock: %w", err)
  44. }
  45. return mutex, nil
  46. }
  47. // 解锁
  48. func UnlockSafe(mutex *redsync.Mutex) error {
  49. if _, err := mutex.Unlock(); err != nil {
  50. if errors.Is(err, redsync.ErrLockAlreadyExpired) {
  51. core.Log.Debug("Lock already expired, ignore error")
  52. return nil
  53. }
  54. return err
  55. }
  56. return nil
  57. }