golang操作redis和lua脚本实现线程安全操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package main

import (
    "fmt"
    "github.com/go-redis/redis"
    "log"
    "sync"
)


func createScript() *redis.Script {
    script := redis.NewScript(`
        local goodsSurplus
        local flag
        local existUserIds    = tostring(KEYS[1])
        local memberUid       = tonumber(ARGV[1])
        local goodsSurplusKey = tostring(KEYS[2])
        local hasBuy = redis.call("sIsMember", existUserIds, memberUid)

        if hasBuy ~= 0 then
          return 0
        end
       

        goodsSurplus =  redis.call("GET", goodsSurplusKey)
        if goodsSurplus == false then
          return 0
        end
       
        -- 没有剩余可抢购物品
        goodsSurplus = tonumber(goodsSurplus)
        if goodsSurplus <= 0 then
          return 0
        end
       
        flag = redis.call("SADD", existUserIds, memberUid)
        flag = redis.call("DECR", goodsSurplusKey)
       
        return 1
    `)
    return script
}


func evalScript(client *redis.Client, userId string, wg *sync.WaitGroup){
    defer wg.Done()
    script := createScript()
    sha, err := script.Load(client.Context(), client).Result()
    if err != nil {
        log.Fatalln(err)
    }
    ret := client.EvalSha(client.Context(), sha, []string{
        "hadBuyUids",
        "goodsSurplus",
    }, userId)
    if result, err := ret.Result();err!= nil {
        log.Fatalf("Execute Redis fail: %v", err.Error())
    }else {
        fmt.Println("")
        fmt.Printf("userid: %s, result: %d", userId, result)
    }
}

func main() {
    var wg sync.WaitGroup
    client := redis.NewClient(&redis.Options{
        Addr:     "localhost:6379",
        Password: "", // no password set
        DB:       0,  // use default DB
    })
    for _, v := range []string{"5824742984", "5824742984", "5824742983", "5824742983", "5824742982", "5824742980"}{
        wg.Add(1)
        go evalScript(client, v, &wg)
    }
    wg.Wait()

}

现在redis中加入20个商品数量
在这里插入图片描述

执行结果:

1
2
3
4
5
6
userid: 5824742984, result: 1
userid: 5824742980, result: 1
userid: 5824742983, result: 1
userid: 5824742982, result: 1
userid: 5824742984, result: 0
userid: 5824742983, result: 0