完整代码传送门
package main
import (
"context"
"fmt"
"net/http"
"redis-distributed-lock/redis_client"
"strconv"
"github.com/go-redsync/redsync/v4"
"github.com/go-redsync/redsync/v4/redis/goredis/v9"
)
const port = 9981
func main() {
http.HandleFunc("/inventory/sale", sale)
fmt.Printf("service start, port: %v\n", port)
if err := http.ListenAndServe(fmt.Sprintf(":%v", port), nil); err != nil {
panic(err)
}
}
const mutexName = "redlock"
func sale(w http.ResponseWriter, r *http.Request) {
pool1 := goredis.NewPool(redis_client.NewClientWithAddr("localhost:6380"))
pool2 := goredis.NewPool(redis_client.NewClientWithAddr("localhost:6381"))
pool3 := goredis.NewPool(redis_client.NewClientWithAddr("localhost:6382"))
rs := redsync.New(pool1, pool2, pool3)
mutex := rs.NewMutex(mutexName)
if err := mutex.Lock(); err != nil {
fmt.Printf("lock failed, err: %v\n", err)
}
reduceInventory()
if ok, err := mutex.Unlock(); !ok || err != nil {
fmt.Printf("unlock failed, err: %v\n", err)
}
}
const inventoryKey = "inventory"
func reduceInventory() (string, error) {
client := redis_client.NewClient()
val, err := client.Get(context.Background(), inventoryKey).Result()
if err != nil {
fmt.Printf("redis get failed, err: %v, key: %v\n", err, inventoryKey)
return "", err
}
inventory, err := strconv.ParseInt(val, 10, 64)
if err != nil {
fmt.Printf("parse int failed, err: %v, val: %v\n", err, inventory)
return "", err
}
var msg string
if inventory > 0 {
if err := client.Set(context.Background(), inventoryKey, inventory-1, 0).Err(); err != nil {
fmt.Printf("redis set failed, err: %v, key: %v\n", err, inventoryKey)
return "", err
}
msg = fmt.Sprintf("inventory: %v, port: %v", inventory-1, port)
} else {
msg = fmt.Sprintf("product slod out, port: %v", port)
}
fmt.Println(msg)
return msg, nil
}