由于redis并没有类似mysql或者mongo的乐观锁机制,并发控制成了一个棘手的问题
这块是可以用redis的watch来做,但是如果能实现乐观锁,那就非常方便了
redis使用lua的基础语法
1 2 3 4 5
| > eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second 1) "key1" 2) "key2" 3) "first" 4) "second"
|
lua可以调用的redis函数
1 2
| redis.call() redis.pcall()
|
简单例子
1 2 3 4 5 6 7 8 9
| local version = redis.call("INCR", KEYS[2]) if version == 1 then redis.call("EXPIRE", KEYS[2], ARGV[3]) end;
if tostring(version) ~= ARGV[2] then return {-1, version} end; return redis.call("SET", KEYS[1], ARGV[1])
|
运行方式:
1
| redis-cli EVAL "$(cat ./helloWorld.lua)" 3 mykey version1 expire 1 1 100
|
redis并发控制
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
| func (db *RedisDB) (key string, val interface{}, versionKey string, versionVal int, versionExpire int) (err error) { if versionExpire == 0 { versionExpire = 100 } storeValue, err := db.getStoreValue(val) if err != nil { return }
conn := db.Option.Pool.Get() defer conn.Close() if err = conn.Err(); err != nil { return err }
script := ` local version = redis.call("INCR", KEYS[2]) if version == 1 then redis.call("EXPIRE", KEYS[2], ARGV[3]) end;
if tostring(version) ~= ARGV[2] then return {-1, version} end; return redis.call("SET", KEYS[1], ARGV[1]) ` getScript := redis.NewScript(3, script) res, err := redis.String(getScript.Do(conn, key, versionKey, "expire", storeValue, versionVal, versionExpire))
if err != nil { utils.Error(err) return } if res == "-1" { }redis return }
|
相关文档
Redis 命令参考 · lua 脚本