Lua 脚本
Lua 脚本 = 把多条 Redis 命令打包成一个原子操作,在 Redis 服务器内部一次执行完。
为什么需要 Lua?
假设:如果锁属于自己,就删除锁。
java
String value = redis.get("lock");
if ("uuid123".equal(value)) {
redis.del("lock");
}这样看起来没问题,但是并发时会出现问题
A 线程:
GET lock
发现:
uuid123此时锁过期。
B 线程:
bash
SET lock uuid456A 线程:
DEL lock但是由于此时锁其实属于 B线程 的 uuid456,所以它删除的其实是 B的锁。
这就是由于 非原子 操作导致的问题。
Lua 解决了什么?
把:
GET
判断
DEL变成:
一次操作Lua:
Lua
if redis.call("get", KEYS[1]) == ARGV[1]
then
return redis.call("del", KEYS[1])
else
return 0
endRedis如何执行?
Redis:
收到脚本
↓
锁住执行
↓
一次执行完
↓
返回结果期间,其他命令不能插队
所以 GET + 判断 + DEL 变成了 原子操作。
为什么叫 Lua?
Lua 是一种轻量级脚本语言。
Redis 内部嵌入了 Lua 解释器。
所以:
Redis 可以执行 Lua 代码。Java 调用
java
DefaultRedisScript<Long> script =
new DefaultRedisScript<>();
script.setScriptText(
"return redis.call('get', KEYS[1])");
script.setResultType(Long.class);
redisTemplate.execute(
script,
Collections.singletonList("count"));常见使用场景
分布式锁
判断是不是自己的锁
再删除
秒杀
判断库存
扣库存
生成购买资格
限流
一分钟只能请求10次
抢红包
判断金额
扣减金额
记录用户