当前位置:   article > 正文

Redis:Lua脚本_redis 集群 lua脚本

redis 集群 lua脚本

本文将讲解如何在Redis-cli和RedisTemplate中使用Lua脚本,以及Lua脚本的部分语法知识。

Lua具体语法请看:Lua 教程 | 菜鸟教程 (runoob.com)

介绍

Lua脚本可以确保一系列Redis命令在同一事务中执行,进而保证命令执行的原子性操作(虽然在redis集群中涉及多个槽位的操作可能无法保证原子性,但是只处理单槽位的key时是可以保证原子性的);有时,需要执行一系列Redis操作,这些操作必须按照特定的顺序和逻辑进行,就可以用Lua脚本将这些操作封装成一个单一的原子事务。

redis-cli

命令方式:EVAL "Lua脚本" numkeys key [key ...] arg [arg ...]

  • "Lua脚本":替换为您要执行的Lua脚本。
  • numkeys:指定Lua脚本中引用的键的数量。
  • key [key ...]:指定Lua脚本引用的键。
  • arg [arg ...]:指定Lua脚本引用的参数。

参数方式: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

RedisTemplate

常用方法:

  1. public <T> T execute(RedisScript<T> script, List<K> keys, Object... args) {
  2. return scriptExecutor.execute(script, keys, args);
  3. }

List keys即key [key ...],Object... args即arg [arg ...]。

示例

同样是模拟分布式锁:

  1. @RestController
  2. public class LockController {
  3. @Autowired
  4. RedisTemplate redisTemplate;
  5. private static final String KEY = "lock";
  6. @GetMapping("/lock")
  7. public boolean lock(@RequestParam String user) {
  8. return redisTemplate.opsForValue().setIfAbsent(KEY, user, 30L, TimeUnit.SECONDS);
  9. }
  10. @GetMapping("/unlock")
  11. public boolean unlock(@RequestParam String user) {
  12. String LuaScript =
  13. "if (redis.call('get',KEYS[1]) == ARGV[1]) then " +
  14. "return redis.call('del',KEYS[1]) " +
  15. "else " +
  16. "return 0 " +
  17. "end";
  18. return (boolean) redisTemplate.execute(new DefaultRedisScript<>(LuaScript, Boolean.class), Arrays.asList(KEY), user);
  19. }
  20. }

user1上锁:

user2无法上锁:

30s后user2可上锁:

30s内user1无法解锁:

30s内user2可解锁:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/神奇cpp/article/detail/921572
推荐阅读
相关标签
  

闽ICP备14008679号