cache.go 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. package dao
  2. import (
  3. "context"
  4. "math/rand"
  5. "time"
  6. "go-common/library/cache/redis"
  7. "go-common/library/log"
  8. )
  9. func randomString(l int) string {
  10. str := "0123456789abcdefghijklmnopqrstuvwxyz"
  11. bytes := []byte(str)
  12. result := []byte{}
  13. r := rand.New(rand.NewSource(time.Now().UnixNano()))
  14. for i := 0; i < l; i++ {
  15. result = append(result, bytes[r.Intn(len(bytes))])
  16. }
  17. return string(result)
  18. }
  19. // Lock .
  20. func (d *Dao) Lock(ctx context.Context, realKey string, ttl int, retry int, retryDelay int) (gotLock bool, lockValue string, err error) {
  21. if retry <= 0 {
  22. retry = 1
  23. }
  24. lockValue = "locked:" + randomString(5)
  25. retryTimes := 0
  26. conn := d.redis.Get(ctx)
  27. defer conn.Close()
  28. for ; retryTimes < retry; retryTimes++ {
  29. var res interface{}
  30. res, err = conn.Do("SET", realKey, lockValue, "PX", ttl, "NX")
  31. if err != nil {
  32. log.Error("redis_lock failed:%s:%s", realKey, err.Error())
  33. break
  34. }
  35. if res != nil {
  36. gotLock = true
  37. break
  38. }
  39. time.Sleep(time.Duration(retryDelay * 1000))
  40. }
  41. return
  42. }
  43. // UnLock .
  44. func (d *Dao) UnLock(ctx context.Context, realKey string, lockValue string) (err error) {
  45. conn := d.redis.Get(ctx)
  46. defer conn.Close()
  47. res, err := redis.String(conn.Do("GET", realKey))
  48. if err != nil {
  49. log.Error("redis_unlock get error:%s:%v", realKey, err)
  50. return
  51. }
  52. if res != lockValue {
  53. err = ErrUnLockGet
  54. return
  55. }
  56. _, err = conn.Do("DEL", realKey)
  57. if err != nil {
  58. log.Error("redis_unlock del error:%s:%v", realKey, err)
  59. }
  60. return
  61. }