Redis中的事务与Lua脚本

本文涉及:Redis中普通事务的实现方式、lua脚本的基础使用以及与Java的结合使用

普通事务

Redis本身提供了multi关键字用来开启事务,exec用来关闭事务。Redis这两个关键字之间的操作是原子性的。

127.0.0.1:6379> multi 
OK
127.0.0.1:6379> set key 1
QUEUED
127.0.0.1:6379> set key2 1
QUEUED
127.0.0.1:6379> get key
QUEUED
127.0.0.1:6379> exec
1) OK
2) OK
3) "1"

普通事务的错误处理机制

命令错误时整个事务全部失败

127.0.0.1:6379> get key
"1"
127.0.0.1:6379> get key2
"1"

127.0.0.1:6379> multi 
OK
127.0.0.1:6379> sets key 3
(error) ERR unknown command `sets`, with args beginning with: `key`, `3`, 
127.0.0.1:6379> set key2 3
QUEUED
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.

127.0.0.1:6379> get key
"1"
127.0.0.1:6379> get key2
"1"

如果语法没有错误,则只会错误的语句受到影响

127.0.0.1:6379> get key
"1"
127.0.0.1:6379> get key2
"1"

127.0.0.1:6379> multi 
OK
127.0.0.1:6379> set key 2
QUEUED
127.0.0.1:6379> set key2 2 2 
QUEUED
127.0.0.1:6379> exec
1) OK
2) (error) ERR syntax error

127.0.0.1:6379> get key
"2"
127.0.0.1:6379> get key2
"1"

为什么要使用Lua脚本

  • ·Lua脚本在Redis中是原子执行的,执行过程中间不会插入其他命令
  • ·Lua脚本可以帮助开发和运维人员创造出自己定制的命令,并可以将这些命令常驻在Redis内存中,实现复用的效果
  • ·Lua脚本可以将多条命令一次性打包,有效地减少网络开销

Lua脚本怎么写

  • 创建lua脚本 就像创建其他的文件一样,新建一个以.lua为后缀的文件,比如说test.lua
  • –-注释
  • 打印语句
print("Hello World!")

4. 常见数据类型

  • boolean、number、string、nil(这个就是我们平常见的null)
  • 一些小的细节问题:
    • type() 用于查看变量的数据类型,比如print(type(10.4*3)) --> number
    • 判断一个变量是否为空时应该使用" a"==“nil"而不是” a"==nil
    • · lua中"1"+“1” 不是合并字符串成ab而是等于2,想要进行字符串拼接需要"1"…“1” -->11
    • lua查看字符串长度应该这样来print(#“Hello”) -->5
    • lua中比较不等于的时候要这样比较:a~= b
    • lua中逻辑运算符是and、or、not

5.变量

a = 5               -- 全局变量
local b = 5         -- 局部变量

6. 条件判断

if maxValue > limit then
          value = limit;
      else if
          value = maxValue;
      else 
          value = 0;
      end

7. 循环

for i, v in ipairs(a) do
    print(i, v)      --i是索引,且是从1开始的。v就是value了。
end

8. 函数

nction test(n)
    if n == 0 then
        return 1
    else
        return -1
    end
end

看完以上几条你的基础其实已经过关了,如果仅仅在操作redis上的话就已经够了。

Redis与Lua脚本

1. 在脚本中与redis进行交互:

local value = redis.call('GET',key);
redis.call('SET',key,value+2);
redis.call('DECR',key);
redis.call('EXPIRE',key,10);

redis.call命令就是在lua中调用redis的相关命令,第一个参数放入要执行的命令,后面的参数放入命令需要的参数就ok了。

2. Redis如何执行Lua脚本:

redis-cli --eval redis-ratelimiter-counter.lua key limit , value1 value2

上方这段命令的意思呢,其实就是告诉redis:请你启动客户端的时候帮我执行一下redis-ratelimiter-counter.lua这个文件,然后呢,执行文件的话有这么几个参数,key、limit 、 value1、value2 细心小伙伴可能会有疑问了,为什么传了4个参数只有一个逗号其他都是空格隔开呢。我们来看一下他们分别是怎么获取的就明白了

local key = KEYS[1];
local limit = KEYS[2];

local value1 = ARGV[1];
local value2 = ARGV[2];

这样的话你是不是看明白了呢,逗号前后的参数是两种不同的传值方式而已。

3. 如何在Java程序中执行lua呢

@Autowired
   private RedisTemplate redisTemplate;
   public void counterConsume(String key, String limit, String lrefreshInterval) {
     DefaultRedisScript<Long> consumeRedisScript=new DefaultRedisScript();
       consumeRedisScript.setResultType(Long.class);
       consumeRedisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("script/redis-ratelimiter-tokenBucket.lua")));//加载lua脚本文件
       List<Object> keyList = new ArrayList();
       keyList.add(key);//通过KEYS[1]取值
       keyList.add(limit);//通过KEYS[2]取值
       List<Object> argvList = new ArrayList();
       argvList.add(lrefreshInterval);//通过ARGV[1]取值
       String result=redisTemplate.execute(redisScript,keyList,argvList).toString();
   }

本文分享自微信公众号 - Java学习录(Javaxuexilu)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-04-26

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏软件开发-青出于蓝

Ehcache配置+Spring 原

以下内容是根据JSR107-Java-Caching-API,加上平时的使用总结的。

20240
来自专栏软件开发-青出于蓝

DispatcherServlet之HandlerAdapter的handle

                                               图1 DispatcherServlet的doService方法时...

10120
来自专栏软件开发-青出于蓝

Which garbage collection strategy is using

indicates ParallelGC is the default strategy. 

6520
来自专栏软件开发-青出于蓝

SpringFramework之DispatcherServlet的初始化简析

                                                           图1 DispatchServlet的类继...

15130
来自专栏软件开发-青出于蓝

DispatcherServlet之view render

                                                  图1 DispatcherServlet的doService...

11310
来自专栏软件开发-青出于蓝

SpringBoot之依赖分析 原

                                                   图1 SpringBoot的模块继承图

15020
来自专栏软件开发-青出于蓝

SpringFramework之DispatcherServlet的getHandler简析

                                              图1 DispatcherServlet的doService方法时序...

9220
来自专栏软件开发-青出于蓝

DispatcherServlet之getHandlerAdapter

                                                        图1 DispatcherServlet的doS...

11220
来自专栏软件开发-青出于蓝

DispatchServlet的分析 原

    首先要说明下,我们发送到服务器端的get、post等请求,都转到doDispatch方法,进行处理。

27920
来自专栏软件开发-青出于蓝

DispatcherServlet之解析controller方法参数上的注解

                             图1 ServletHandlerMethodInvoker的invokeHandlerMethod方...

11730

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励