distribute_lock.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. package utils
  2. import (
  3. "context"
  4. "errors"
  5. "sync"
  6. "time"
  7. "gd_auth_check/common.in/cache"
  8. "go.etcd.io/etcd/client"
  9. )
  10. var lockKey = "/gd/lock"
  11. var lockValue = "locked"
  12. var etcdClient client.Client
  13. var keyApi client.KeysAPI
  14. var gmutex sync.Mutex
  15. var gm = map[string]string{}
  16. func SetEtcdKeyApi(c client.Client) {
  17. if keyApi == nil {
  18. keyApi = client.NewKeysAPI(c)
  19. }
  20. }
  21. func setKey(keyApi client.KeysAPI, key string, value string, prevExist client.PrevExistType) error {
  22. opts := &client.SetOptions{
  23. PrevExist: prevExist,
  24. TTL: 10 * time.Second,
  25. }
  26. _, err := keyApi.Set(context.Background(), key, value, opts)
  27. return err
  28. }
  29. func delKey(keyApi client.KeysAPI, key string) error {
  30. _, err := keyApi.Delete(context.Background(), key, nil)
  31. e, _ := err.(client.Error)
  32. if e.Code == client.ErrorCodeKeyNotFound {
  33. return nil
  34. }
  35. return err
  36. }
  37. func lock(realLockKey string) error {
  38. var err error
  39. err = setKey(keyApi, realLockKey, lockValue, client.PrevNoExist)
  40. if err == nil {
  41. return nil
  42. }
  43. return err
  44. }
  45. func redisLock(key string) error {
  46. v, err := cache.Redis.SetNxEx(key, "-", 10)
  47. if v == false {
  48. return errors.New("locked:" + key)
  49. }
  50. return err
  51. }
  52. func redisUnlock(key string) error {
  53. _, err := cache.Redis.Del(key)
  54. return err
  55. }
  56. func localLock(key string) bool {
  57. now := time.Now().Unix()
  58. for {
  59. gmutex.Lock()
  60. if _, ok := gm[key]; ok == false {
  61. gm[key] = "-"
  62. gmutex.Unlock()
  63. return true
  64. }
  65. gmutex.Unlock()
  66. if time.Now().Unix()-now >= 60 {
  67. return false
  68. }
  69. time.Sleep(50 * time.Millisecond)
  70. }
  71. }
  72. func localUnlock(key string) {
  73. gmutex.Lock()
  74. if _, ok := gm[key]; ok == true {
  75. delete(gm, key)
  76. }
  77. if len(gm) == 0 {
  78. gm = map[string]string{}
  79. }
  80. gmutex.Unlock()
  81. }
  82. func Lock(flag string) error {
  83. realLockKey := lockKey + "/" + flag
  84. if localLock(realLockKey) == false {
  85. return errors.New("local lock timeout")
  86. }
  87. count := 0
  88. for {
  89. count++
  90. if count > 1000 {
  91. localUnlock(realLockKey)
  92. return errors.New("max count")
  93. }
  94. err := redisLock(realLockKey)
  95. if err == nil {
  96. return nil
  97. }
  98. time.Sleep(400 * time.Millisecond)
  99. }
  100. return nil
  101. }
  102. func UnLock(flag string) error {
  103. err := redisUnlock(lockKey + "/" + flag)
  104. localUnlock(lockKey + "/" + flag)
  105. return err
  106. }