locker.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. package redisclient
  2. import (
  3. "app/commons/core"
  4. "errors"
  5. "fmt"
  6. "github.com/go-redsync/redsync/v4"
  7. "time"
  8. )
  9. // Lock 获取分布式锁 -- 指定超时时间
  10. func LockWithTime(lockKey string, expSecond int32) (*redsync.Mutex, error) {
  11. opts := LockOptions{
  12. Expiration: expSecond, // 锁的过期时间(秒)
  13. MaxRetries: int(expSecond), // 最大重试次数
  14. RetryDelay: 1 * time.Second, // 重试间隔
  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. // Lock 获取分布式锁
  29. func Lock(lockKey string) (*redsync.Mutex, error) {
  30. opts := LockOptions{
  31. Expiration: int32(3), // 锁的过期时间(秒)
  32. MaxRetries: 8, // 最大重试次数
  33. RetryDelay: 300 * time.Millisecond, // 重试间隔
  34. }
  35. // 默认值
  36. if opts.Expiration <= 0 {
  37. opts.Expiration = DefaultLockOptions.Expiration
  38. }
  39. if opts.MaxRetries <= 0 {
  40. opts.MaxRetries = DefaultLockOptions.MaxRetries
  41. }
  42. if opts.RetryDelay <= 0 {
  43. opts.RetryDelay = DefaultLockOptions.RetryDelay
  44. }
  45. return LockWithOptions(lockKey, opts)
  46. }
  47. // LockWithOptions 使用指定的选项获取分布式锁
  48. // 返回锁定的 mutex,失败时返回错误
  49. // 使用完后需调用 Unlock() 释放锁
  50. // 获取锁
  51. func LockWithOptions(lockKey string, opts LockOptions) (*redsync.Mutex, error) {
  52. if opts.Expiration <= 0 || opts.MaxRetries < 1 || opts.RetryDelay < 0 {
  53. return nil, errors.New("invalid lock options")
  54. }
  55. mutex := redisSync().NewMutex(
  56. lockKey,
  57. redsync.WithExpiry(time.Duration(opts.Expiration)*time.Second),
  58. redsync.WithTries(opts.MaxRetries),
  59. redsync.WithRetryDelay(opts.RetryDelay),
  60. )
  61. if err := mutex.Lock(); err != nil {
  62. return nil, fmt.Errorf("failed to acquire lock: %w", err)
  63. }
  64. return mutex, nil
  65. }
  66. // 解锁
  67. func UnlockSafe(mutex *redsync.Mutex) error {
  68. if _, err := mutex.Unlock(); err != nil {
  69. if errors.Is(err, redsync.ErrLockAlreadyExpired) {
  70. core.Log.Debug("Lock already expired, ignore error")
  71. return nil
  72. }
  73. return err
  74. }
  75. return nil
  76. }