赞
踩
本文将讲解如何在Redis-cli和RedisTemplate中使用Lua脚本,以及Lua脚本的部分语法知识。
Lua具体语法请看:Lua 教程 | 菜鸟教程 (runoob.com)
Lua脚本可以确保一系列Redis命令在同一事务中执行,进而保证命令执行的原子性操作(虽然在redis集群中涉及多个槽位的操作可能无法保证原子性,但是只处理单槽位的key时是可以保证原子性的);有时,需要执行一系列Redis操作,这些操作必须按照特定的顺序和逻辑进行,就可以用Lua脚本将这些操作封装成一个单一的原子事务。
命令方式:EVAL "Lua脚本" numkeys key [key ...] arg [arg ...]
参数方式:redis-cli --eval 脚本地址 keys... , args...
(分布式锁中为了保证一个线程只能解除自己的锁,使用setnx命令后的del命令必须判断该锁是否是它自身定下的,以免网络延迟导致del命令删除其他线程定下的锁)
先使用setnx命令,模拟一个线程获得锁:
127.0.0.1:6379> set lock lock-user1 NX EX 30
1
然后使用lua脚本进行释放锁:
127.0.0.1:6379> eval "if redis.call('get',KEYS[1])==ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end" 1 lock lock-user1
1
该命令中使用redis.call调用get lock并判断返回值是否是ARGV[1],即lock-user1,如果是,说明该锁就是它定下的,就使用del命令解锁并返回值,否则直接返回0说明执行失败。
127.0.0.1:6379> eval "if redis.call('get',KEYS[1])==ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end" 1 lock lock-user2 0
user2就无法解除该锁。
也可以使用参数方式:
lua.lua脚本文件:
if (redis.call('get',KEYS[1]) == ARGV[1]) then
return redis.call('del',KEYS[1])
else
return 0
end;
执行:
$ redis-cli -a 20030322 --eval /home/chilun/Redis/lua.lua lock , lock-user1
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
(integer) 1
常用方法:
- public <T> T execute(RedisScript<T> script, List<K> keys, Object... args) {
- return scriptExecutor.execute(script, keys, args);
- }
List keys即key [key ...],Object... args即arg [arg ...]。
同样是模拟分布式锁:
- @RestController
- public class LockController {
- @Autowired
- RedisTemplate redisTemplate;
- private static final String KEY = "lock";
-
- @GetMapping("/lock")
- public boolean lock(@RequestParam String user) {
- return redisTemplate.opsForValue().setIfAbsent(KEY, user, 30L, TimeUnit.SECONDS);
- }
-
- @GetMapping("/unlock")
- public boolean unlock(@RequestParam String user) {
- String LuaScript =
- "if (redis.call('get',KEYS[1]) == ARGV[1]) then " +
- "return redis.call('del',KEYS[1]) " +
- "else " +
- "return 0 " +
- "end";
- return (boolean) redisTemplate.execute(new DefaultRedisScript<>(LuaScript, Boolean.class), Arrays.asList(KEY), user);
- }
- }
user1上锁:
user2无法上锁:
30s后user2可上锁:
30s内user1无法解锁:
30s内user2可解锁:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。