redsync项目地址

  1. package main
  2. import (
  3. goredislib "github.com/go-redis/redis/v8"
  4. "github.com/go-redsync/redsync/v4"
  5. "github.com/go-redsync/redsync/v4/redis/goredis/v8"
  6. )
  7. func main() {
  8. // Create a pool with go-redis (or redigo) which is the pool redisync will
  9. // use while communicating with Redis. This can also be any pool that
  10. // implements the `redis.Pool` interface.
  11. client := goredislib.NewClient(&goredislib.Options{
  12. Addr: "localhost:6379",
  13. })
  14. pool := goredis.NewPool(client) // or, pool := redigo.NewPool(...)
  15. // Create an instance of redisync to be used to obtain a mutual exclusion
  16. // lock.
  17. rs := redsync.New(pool)
  18. // Obtain a new mutex by using the same name for all instances wanting the
  19. // same lock.
  20. mutexname := "my-global-mutex"
  21. mutex := rs.NewMutex(mutexname)
  22. // Obtain a lock for our given mutex. After this is successful, no one else
  23. // can obtain the same lock (the same mutex name) until we unlock it.
  24. if err := mutex.Lock(); err != nil {
  25. panic(err)
  26. }
  27. // Do your work that requires the lock.
  28. // Release the lock so other processes or threads can obtain a lock.
  29. if ok, err := mutex.Unlock(); !ok || err != nil {
  30. panic("unlock failed")
  31. }
  32. }

redsync源码解读

  1. setnx的作用

    将获取和设置值变成原子性的操作

  2. 如果我的服务挂掉了- 死锁

    1. 设置过期时间
    2. 如果你设置了过期时间,那么如果过期时间到了我的业务逻辑没有执行完怎么办?
      1. 在过期之前刷新一下
      2. 需要自己去启动协程完成延时的工作
        1. 延时的接口可能会带来负面影响 - 如果其中某一个服务hung住了, 2s就能执行完,但是你hung住那么你就会一直去申请延长锁,导致别人永远获取不到锁,这个很要命
  3. 分布锁需要解决的问题 - lua脚本去做

    1. 互斥性 - setnx
    2. 死锁
    3. 安全性
      1. 锁只能被持有该锁的用户删除,不能被其他用户删除
        1. 当时设置的value值是多少只有当时的g才能知道
        2. 在删除的时取出redis中的值和当前自己保存下来的值对比一下
  4. 即使你这样实现了分布式但是还是会有问题 - redlock