当前位置:   article > 正文

golang redis实现分布式锁_golang redis分布式锁

golang redis分布式锁
  1. package main
  2. import (
  3. "context"
  4. "fmt"
  5. "time"
  6. "github.com/go-redis/redis/v8"
  7. )
  8. func main() {
  9. redisCli := redis.NewClient(&redis.Options{
  10. Addr: "127.0.0.1:6379",
  11. Password: "123456",
  12. DB: 0,
  13. })
  14. redisLock := NewRedisLock("test_key1", "test_value1", 1*time.Minute, redisCli)
  15. locked, err := redisLock.TryLock()
  16. fmt.Printf("locked:%v,err:%v\n", locked, err)
  17. }
  18. // RedisLock redis实现的分布式锁
  19. type RedisLock struct {
  20. key string
  21. value string // 唯一标识,一般使用uuid
  22. expiration time.Duration
  23. redisCli *redis.Client
  24. }
  25. func NewRedisLock(key, value string, expiration time.Duration, cli *redis.Client) *RedisLock {
  26. if key == "" || value == "" || cli == nil {
  27. return nil
  28. }
  29. return &RedisLock{
  30. key: key,
  31. value: value,
  32. expiration: expiration,
  33. redisCli: cli,
  34. }
  35. }
  36. // Lock 添加分布式锁,expiration过期时间,小于等于0,不过期,需要通过 UnLock方法释放锁
  37. func (rl *RedisLock) Lock() (bool, error) {
  38. result, err := rl.redisCli.SetNX(context.Background(), rl.key, rl.value, rl.expiration).Result()
  39. if err != nil {
  40. return false, err
  41. }
  42. return result, nil
  43. }
  44. func (rl *RedisLock) TryLock(waitTime time.Duration) (bool, error) {
  45. var onceWaitTime = 20 * time.Millisecond
  46. if waitTime < onceWaitTime {
  47. waitTime = onceWaitTime
  48. }
  49. for index := 0; index < int(waitTime/onceWaitTime); index++ {
  50. locked, err := rl.Lock()
  51. if locked || err != nil {
  52. return locked, err
  53. }
  54. time.Sleep(onceWaitTime)
  55. }
  56. return false, nil
  57. }
  58. func (rl *RedisLock) UnLock() (bool, error) {
  59. script := redis.NewScript(`
  60. if redis.call("get", KEYS[1]) == ARGV[1] then
  61. return redis.call("del", KEYS[1])
  62. else
  63. return 0
  64. end
  65. `)
  66. result, err := script.Run(context.Background(), rl.redisCli, []string{rl.key}, rl.value).Int64()
  67. if err != nil {
  68. return false, err
  69. }
  70. return result > 0, nil
  71. }
  72. // RefreshLock 存在则更新过期时间,不存在则创建key
  73. func (rl *RedisLock) RefreshLock() (bool, error) {
  74. script := redis.NewScript(`
  75. local val = redis.call("GET", KEYS[1])
  76. if not val then
  77. redis.call("setex", KEYS[1], ARGV[2], ARGV[1])
  78. return 2
  79. elseif val == ARGV[1] then
  80. return redis.call("expire", KEYS[1], ARGV[2])
  81. else
  82. return 0
  83. end
  84. `)
  85. result, err := script.Run(context.Background(), rl.redisCli, []string{rl.key}, rl.value, rl.expiration/time.Second).Int64()
  86. if err != nil {
  87. return false, err
  88. }
  89. return result > 0, nil
  90. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/681139
推荐阅读
相关标签
  

闽ICP备14008679号