前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Redis系列之使用Lua脚本

Redis系列之使用Lua脚本

作者头像
SmileNicky
发布2024-01-14 10:12:39
1350
发布2024-01-14 10:12:39
举报
文章被收录于专栏:Nicky's blogNicky's blog

什么是lua脚本?

lua语言是一个轻量级的脚本语言,可以嵌入其他语言中使用,调用宿主语言的功能。lua语法简单,小巧,源码一共才200多K,本身不会有太强的功能,很多的语言也支持lua语言,比如redis、Nginx

redis语言中完美嵌入了lua脚本功能,redis可以调用lua脚本中的api,lua脚本也可以调用redis中的命令

redis调用lua脚本

在redis中调用lua脚本,需要使用eval指令

代码语言:javascript
复制
127.0.0.1:6379>eval "return 'hello'" 0
"hello"

调用lua脚本,动态传入参数,其中表达式script后面第一个参数nkey表示key的对应位置,后面的表示key和对应的参数argv

代码语言:javascript
复制
# script脚本后面,第一个参数1表示key为其后的第一个参数,也就是1,如何key后面的参数都是ARGV
127.0.0.1:6379>eval "if KEYS[1]=='1' then return ARGV[1] end return ARGV[2]" 1 1 'hello' 'hi'
"hello"
127.0.0.1:6379>eval "if KEYS[1]=='1' then return ARGV[1] end return ARGV[2]" 1 1 'hello' 'hi'
"hi"

lua脚本调用redis命令

使用lua调用redis的命令,需要使用redis.call调用

代码语言:javascript
复制
# key为0表示能获取到锁
127.0.0.1:6379>eval "local key = redis.call('exists',KEYS[1]) if key==0 then return redis.call('set',KEYS[1],ARGV[1]) end return 1" 1 orderId01 1

写个lua脚本,来实现一个简单的分布锁锁

代码语言:javascript
复制
private static final String LOCK_LUA_SCRIPT = "local lockParam = redis.call('exists', KEYS[1])\n" +
            "if lockParam == 0 then\n" +
            "redis.call('set', KEYS[1], ARGV[1])\n" +
            "redis.call('expire', KEYS[1], ARGV[2])\n" +
            "end\n" +
            "return lockParam\n";

简单实现抢单的业务

代码语言:javascript
复制
  @Autowired
    private RedisTemplate redisTemplate;

    @Test
    public void testLua() {
        Long orderId = IdUtil.getSnowflake().nextId();
        String lockKey = "order:"+orderId;
        String requestId = IdUtil.randomUUID();
        try {
            Long lock = (Long) redisTemplate.execute(RedisScript.of(LOCK_LUA_SCRIPT, Long.class), Arrays.asList(lockKey), requestId, 30);
            // 抢得到锁
            if (lock == 0) {
                // 模拟业务执行10s
                TimeUnit.MILLISECONDS.sleep(10*1000);
            }
            log.info("lock:[{}]", lock);
        } catch (Exception e) {
            testRelease(lockKey, requestId);
        } finally {
            testRelease(lockKey, requestId);
        }
    }

锁释放的,也通过lua脚本实现,主要是保证原子性

代码语言:javascript
复制
 private String UNLOCK_LUA_SCRIPT = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";

@Test
public void testRelease(String lockKey, String lockValue) {
    redisTemplate.execute(RedisScript.of(UNLOCK_LUA_SCRIPT, Long.class), Arrays.asList(lockKey), lockValue);
}

Lua脚本使用场景

  • 保证原子性地执行多个命令
  • 需要返回中间值组合编排后面的命令
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2024-01-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是lua脚本?
  • redis调用lua脚本
  • lua脚本调用redis命令
  • Lua脚本使用场景
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档