distribute_lock.go 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. package utils
  2. import (
  3. "context"
  4. "adm-ads/common.in/cache"
  5. "fmt"
  6. "time"
  7. )
  8. type Lock struct {
  9. Key string
  10. Ttl int64
  11. cancel context.CancelFunc
  12. }
  13. // 监听过期
  14. func (lock *Lock) WatchLock(ctx context.Context) {
  15. sleepTime := time.Duration(lock.Ttl * 2 / 3)
  16. t1 := time.Tick(sleepTime * time.Second)
  17. for {
  18. select {
  19. case <-t1:
  20. cache.Redis.Expire(lock.Key, lock.Ttl)
  21. case <-ctx.Done():
  22. return
  23. }
  24. }
  25. }
  26. // 停止监听
  27. func (lock *Lock) StopWatch() {
  28. lock.cancel()
  29. }
  30. // 加分布式锁
  31. func (lock *Lock) RedisLock() (bool,error) {
  32. if lock.Key == "" || lock.Ttl <= 0 {
  33. return false,fmt.Errorf("参数错误")
  34. }
  35. res, err := cache.Redis.SetNxEx(lock.Key, "lock", lock.Ttl)
  36. // redis 操作失败
  37. if err != nil {
  38. return false,err
  39. }
  40. // 上锁成功
  41. if res {
  42. ctx, cancel := context.WithCancel(context.Background())
  43. lock.cancel = cancel
  44. go lock.WatchLock(ctx)
  45. return true,nil
  46. }
  47. return false,nil
  48. }
  49. func (lock *Lock) TryRedisLock() error {
  50. for{
  51. islock ,err := lock.RedisLock()
  52. if err != nil{
  53. return err
  54. }else{
  55. if islock{
  56. return nil
  57. }else{
  58. time.Sleep(1*time.Second)
  59. }
  60. }
  61. }
  62. }
  63. // 释放分布式锁
  64. func (lock *Lock) RedisUnlock() {
  65. // 停止监听
  66. lock.StopWatch()
  67. // 删除分布式锁
  68. cache.Redis.Del(lock.Key)
  69. }