From 9092120d563fb3c615f6c7fa9f91c8dc47b7a671 Mon Sep 17 00:00:00 2001 From: liwei1dao Date: Thu, 14 Jul 2022 16:06:12 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0redis=20lua=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lego/sys/redis/cluster/core.go | 18 ++++++++++ lego/sys/redis/core.go | 21 ++++++++++++ lego/sys/redis/redis.go | 20 +++++++---- lego/sys/redis/single/core.go | 18 ++++++++++ lego/sys/redis/sys_test.go | 62 ++++++++++++++++++++++++++-------- 5 files changed, 118 insertions(+), 21 deletions(-) diff --git a/lego/sys/redis/cluster/core.go b/lego/sys/redis/cluster/core.go index bfc85f786..ca771708e 100644 --- a/lego/sys/redis/cluster/core.go +++ b/lego/sys/redis/cluster/core.go @@ -89,3 +89,21 @@ func (this *Redis) UnLock(key string) (err error) { err = this.Delete(key) return } + +//lua Script +func (this *Redis) NewScript(src string) *redis.StringCmd { + script := redis.NewScript(src) + return script.Load(this.getContext(), this.client) +} +func (this *Redis) Eval(script string, keys []string, args ...interface{}) *redis.Cmd { + return this.client.Eval(this.getContext(), script, keys, args...) +} +func (this *Redis) EvalSha(sha1 string, keys []string, args ...interface{}) *redis.Cmd { + return this.client.EvalSha(this.getContext(), sha1, keys, args...) +} +func (this *Redis) ScriptExists(hashes ...string) *redis.BoolSliceCmd { + return this.client.ScriptExists(this.getContext(), hashes...) +} +func (this *Redis) ScriptLoad(script string) *redis.StringCmd { + return this.client.ScriptLoad(this.getContext(), script) +} diff --git a/lego/sys/redis/core.go b/lego/sys/redis/core.go index d07f5ab1c..dd4ab55a7 100644 --- a/lego/sys/redis/core.go +++ b/lego/sys/redis/core.go @@ -16,6 +16,7 @@ type ( Pipeline(ctx context.Context, fn func(pipe redis.Pipeliner) error) (err error) TxPipelined(ctx context.Context, fn func(pipe redis.Pipeliner) error) (err error) Watch(ctx context.Context, fn func(*redis.Tx) error, keys ...string) (err error) + /*Key*/ Delete(key string) (err error) ExistsKey(key string) (iskeep bool, err error) @@ -112,6 +113,12 @@ type ( ZScore(key string, member string) (result float64, err error) ZUnionStore(dest string, store *redis.ZStore) (result int64, err error) ZScan(key string, _cursor uint64, match string, count int64) (keys []string, cursor uint64, err error) + + /*Lua Script*/ + NewScript(src string) *redis.StringCmd + Eval(script string, keys []string, args ...interface{}) *redis.Cmd + EvalSha(sha1 string, keys []string, args ...interface{}) *redis.Cmd + ScriptExists(hashes ...string) *redis.BoolSliceCmd } ISys interface { @@ -445,3 +452,17 @@ func ZUnionStore(dest string, store *redis.ZStore) (result int64, err error) { func ZScan(key string, _cursor uint64, match string, count int64) (keys []string, cursor uint64, err error) { return defsys.ZScan(key, _cursor, match, count) } + +/*Lua Script*/ +func NewScript(src string) *redis.StringCmd { + return defsys.NewScript(src) +} +func Eval(script string, keys []string, args ...interface{}) *redis.Cmd { + return defsys.Eval(script, keys, args...) +} +func EvalSha(sha1 string, keys []string, args ...interface{}) *redis.Cmd { + return defsys.Eval(sha1, keys, args...) +} +func ScriptExists(hashes ...string) *redis.BoolSliceCmd { + return defsys.ScriptExists(hashes...) +} diff --git a/lego/sys/redis/redis.go b/lego/sys/redis/redis.go index 5ac350bbb..98fdacad0 100644 --- a/lego/sys/redis/redis.go +++ b/lego/sys/redis/redis.go @@ -45,7 +45,6 @@ func (this *Redis) init() (err error) { } return } - func (this *Redis) Close() (err error) { return this.client.Close() } @@ -67,15 +66,12 @@ func (this *Redis) Lock(key string, outTime int) (result bool, err error) { func (this *Redis) UnLock(key string) (err error) { return this.client.UnLock(key) } - func (this *Redis) Delete(key string) (err error) { return this.client.Delete(key) } - func (this *Redis) ExistsKey(key string) (iskeep bool, err error) { return this.client.ExistsKey(key) } - func (this *Redis) Expire(key string, expire time.Duration) (err error) { return this.client.Expire(key, expire) } @@ -106,8 +102,6 @@ func (this *Redis) RenameNX(oldkey string, newkey string) (err error) { func (this *Redis) Keys(pattern string) (keys []string, err error) { return this.client.Keys(pattern) } - -///获取键类型 func (this *Redis) Type(key string) (ty string, err error) { return this.client.Type(key) } @@ -355,6 +349,20 @@ func (this *Redis) ZScan(key string, _cursor uint64, match string, count int64) return this.client.ZScan(key, _cursor, match, count) } +//lua Script +func (this *Redis) NewScript(src string) *redis.StringCmd { + return this.client.NewScript(src) +} +func (this *Redis) Eval(script string, keys []string, args ...interface{}) *redis.Cmd { + return this.client.Eval(script, keys, args...) +} +func (this *Redis) EvalSha(sha1 string, keys []string, args ...interface{}) *redis.Cmd { + return this.client.EvalSha(sha1, keys, args...) +} +func (this *Redis) ScriptExists(hashes ...string) *redis.BoolSliceCmd { + return this.client.ScriptExists(hashes...) +} + //Codec--------------------------------------------------------------------------------------------------------------------------------------- func (this *Redis) Marshal(v interface{}) ([]byte, error) { if this.options.Codec != nil { diff --git a/lego/sys/redis/single/core.go b/lego/sys/redis/single/core.go index 58dd8c807..32944d43b 100644 --- a/lego/sys/redis/single/core.go +++ b/lego/sys/redis/single/core.go @@ -88,3 +88,21 @@ func (this *Redis) UnLock(key string) (err error) { err = this.Delete(key) return } + +//lua Script +func (this *Redis) NewScript(src string) *redis.StringCmd { + script := redis.NewScript(src) + return script.Load(this.getContext(), this.client) +} +func (this *Redis) Eval(script string, keys []string, args ...interface{}) *redis.Cmd { + return this.client.Eval(this.getContext(), script, keys, args...) +} +func (this *Redis) EvalSha(sha1 string, keys []string, args ...interface{}) *redis.Cmd { + return this.client.EvalSha(this.getContext(), sha1, keys, args...) +} +func (this *Redis) ScriptExists(hashes ...string) *redis.BoolSliceCmd { + return this.client.ScriptExists(this.getContext(), hashes...) +} +func (this *Redis) ScriptLoad(script string) *redis.StringCmd { + return this.client.ScriptLoad(this.getContext(), script) +} diff --git a/lego/sys/redis/sys_test.go b/lego/sys/redis/sys_test.go index 522ca0f87..aa1c08ae3 100644 --- a/lego/sys/redis/sys_test.go +++ b/lego/sys/redis/sys_test.go @@ -3,6 +3,7 @@ package redis_test import ( "encoding/json" "fmt" + "log" "os" "sync" "testing" @@ -181,25 +182,56 @@ func Test_Redis_Encoder_int(t *testing.T) { } func Test_Redis_Encoder_Hash(t *testing.T) { - // err := redis.HMSet("test:1005", &TestData{Name: "liwei1dao", Agr: 12, Sub: &TestAny{SubName: "test", Age: 20}}) - // fmt.Printf("err:%v\n", err) - - // data := &TestData{} - // err = redis.HGetAll("test:1005", data) - // fmt.Printf("data:%v err:%v\n", data, err) - - // redis.HSet("test:1003", "Name", "eeee") name := "" err := redis.HGet("test:103", "name", &name) if err != nil { fmt.Println(err) } fmt.Println(name) - - // data1 := map[string]*TestData{"li_1": {Name: "liwei2dao", Agr: 56}, "li_2": {Name: "liwei3dao", Agr: 78}} - // err := redis.HMSet("test:1004", data1) - // fmt.Printf("err:%v\n", err) - // data2 := make(map[string]*TestData) - // err = redis.HGetAll("test:1004", data2) - // fmt.Printf("data2:%v err:%v\n", data2, err) +} + +//测试redis lua 脚本 +func Test_Redis_Lua(t *testing.T) { + 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 + `) + sha, err := script.Result() + if err != nil { + log.Fatalln(err) + } + ret := redis.EvalSha(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) + } }