美文网首页
Redis深度历险-分布式锁

Redis深度历险-分布式锁

作者: 突击手平头哥 | 来源:发表于2021-07-23 07:31 被阅读0次

Redis分布式锁

Redis可以用来实现分布式锁,有两种实现方式:通过setnx实现的悲观锁和通过watch实现的乐观锁

悲观锁

package main

import (
    "fmt"
    "github.com/garyburd/redigo/redis"
    "log"
    "math/rand"
    "strconv"
)

func  main() {
    conn, err := redis.Dial("tcp", "127.0.0.1:6379")
    if err != nil {
        log.Fatal(err)
    }

    tag := strconv.Itoa(rand.Int())
    reply, err := conn.Do("set", "lock", tag, "ex", "1", "nx")
    if reply == "OK" {
        //do something
    }

    reply, err = conn.Do("eval",
        "if redis.call('get', KEYS[1]) == ARGV[1] then " +
        "   return redis.call('del', KEYS[1])" +
        "else" +
        "   return 0 " +
        "end", "1", "lock", tag)
    
    if reply == int64(1) {
        fmt.Println("release lock")
    }

}

本质就是通过set+nx的方式只允许一个客户端加锁成功,主要的问题在于:

  • 要注意给锁加上超时,否则当客户端断了就再也没人解锁了
  • 在解锁的时候,注意只能删除自己加的锁,所以要做delifequals这样的原子指令

乐观锁

package main

import (
    "fmt"
    "github.com/garyburd/redigo/redis"
    "log"
)

func  main() {
    conn, err := redis.Dial("tcp", "127.0.0.1:6379")
    if err != nil {
        log.Fatal(err)
    }

    conn.Do("set", "lock", "1")
    conn.Do("watch", "lock")
    //conn.Do("set", "lock", "2")

    conn.Do("multi")
    conn.Do("set", "key", "123")
    reply, err := conn.Do("exec")

    fmt.Println(reply, err)

}

乐观锁则是利用watch+multi+exec机制来实现,在exec时会检查watch的值是否有发生变化

其他问题

在哨兵模式下,如果主节点挂掉就会将备用节点启动替换为主节点;

以上的这些问题就在于如果在主节点上获取了锁但是主节点还没有同步到备用节点上就挂掉了,那么就可能出现另外一个客户端过来加锁成功

相关文章

网友评论

      本文标题:Redis深度历险-分布式锁

      本文链接:https://www.haomeiwen.com/subject/uhsumltx.html