是一种轻量的脚本语言,设计目的是为了嵌入应用程序中,为应用程序提供灵活的扩展和定制功能
特性:
这里主要是用redis的时候了解了一下lua脚本,所以这里主要记录redis中的使用
lua可以用redis.call()
调用redis命令
luareturn redis.call('GET',KEYS[1])
redis中的一些lua命令
lua-- 相当于SETEX key1 60 10 EVAL "redis.call('SET',KEYS[1],ARGV[1]);redis.call("EXIPRE',KEYS[1],ARGV[2]);return 1" 1 key1 10 60
SCRIPT LOAD
EVALSHA
SCRIPT EXISTS
SCRIPT FLUSH
SCRIPT KILL
SHUTDOWN NOSAVE
命令,停止整个redis进程来停止脚本的运行,防止不完整的信息写入数据库消费者案例,主要是进行原子操作以及防抖重复购买,以及避免超卖
golangpackage main import ( "fmt" "github.com/gomodule/redigo/redis" "math/rand" _redis "redis-example/redis" "time" ) const Script = ` if redis.call("EXISTS",KEYS[1]) ==1 then return 2 else if redis.call("EXISTS",KEYS[2]) == 1 and tonumber(redis.call("GET",KEYS[2]))>0 then redis.call("DECR",KEYS[2]) redis.call("HINCRBY",KEYS[1].."buy",KEYS[2],1) redis.call("SET",KEYS[1],1) redis.call("EXPIRE",KEYS[1],1) return 1 else return 0 end end ` func producer(c redis.Conn, product string) { defer c.Close() for { // 自增 c.Do("INCR", product) fmt.Println(product + "+1") time.Sleep(time.Second) } } func consumer(c redis.Conn, user string, product string) { defer c.Close() lua := redis.NewScript(2, Script) for { res, err := lua.Do(c, user, product) if err != nil { fmt.Println(err, 111) return } if r, _ := res.(int64); r == 1 { fmt.Println(user + " buy " + product) } else if r == 0 { fmt.Println("Unlucky " + user + "," + " the " + product + " is sold out!") } else { fmt.Println(user + " you hava buy in this second") } time.Sleep(time.Millisecond * time.Duration(rand.Intn(10)*100)) } } func main() { c := _redis.GetRedisConn() c.Do("FLUSHALL") c.Close() go producer(_redis.GetRedisConn(), "apple") go producer(_redis.GetRedisConn(), "pineapple") go consumer(_redis.GetRedisConn(), "1", "apple") go consumer(_redis.GetRedisConn(), "2", "apple") go consumer(_redis.GetRedisConn(), "2", "pineapple") time.Sleep(time.Second * 10) //go consumer(_redis.GetRedisConn(), "用户1") }
本文作者:Malyue
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!