Redis - Lua 脚本

1. hello world

> print("Hello World!")

我们也可以将代码修改为如下形式来执行脚本(在开头添加:#!/usr/local/bin/lua):

#!/usr/local/bin/lua

print("Hello World!")
print("www.runoob.com")

运行

./hello.lua 
Hello World!
www.runoob.com

2. 数据类型

在这里插入图片描述

3. 变量

Lua 中的变量全是全局变量,那怕是语句块或是函数里,除非用 local 显式声明为局部变量。

-- test.lua 文件脚本
a = 5               -- 全局变量
local b = 5         -- 局部变量

function joke()
    c = 5           -- 全局变量
    local d = 6     -- 局部变量
end

joke()
print(c,d)          --> 5 nil

do
    local a = 6     -- 局部变量
    b = 6           -- 对局部变量重新赋值
    print(a,b);     --> 6 6
end

print(a,b)      --> 5 6
a, b, c = 0, 1
print(a,b,c)             --> 0   1   nil
 
a, b = a+1, b+1, b+2     -- value of b+2 is ignored
print(a,b)               --> 1   2
 
a, b, c = 0
print(a,b,c)             --> 0   nil   nil

4. 循环

while循环

a=10
while( a < 20 )
do
   print("a 的值为:", a)
   a = a+1
end

for循环

  1. 数值循环 , f(x)只会在循环开始前执行一次
#!/usr/local/bin/lua  
function f(x)  
    print("function")  
    return x*2  
end  
for i=1,f(5) 
do 
	print(i)  
end

结果:

function
1
2
3
4
5
6
7
8
9
10
  1. 泛型循环
    i是数组索引值,v是对应索引的数组元素值。ipairs是Lua提供的一个迭代器函数,用来迭代数组。
--打印数组a的所有值  
a = {"one", "two", "three"}
for i, v in ipairs(a) 
do
    print(i, v)
end 

5. 判断

--[ 定义变量 --]
a = 100;
--[ 检查条件 --]
if( a < 20 )
then
   --[ if 条件为 true 时执行该语句块 --]
   print("a 小于 20" )
else
   --[ if 条件为 false 时执行该语句块 --]
   print("a 大于 20" )
end
print("a 的值为 :", a)

结果

a 大于 20
a 的值为 :    100

6. 数组

array = {}

for i= -2, 2 do
   array[i] = i *2
end

for i = -2,2 do
   print(array[i])
end

结果

-4
-2
0
2
4

7. 迭代器

格式:

for k, v in pairs(t) do
    print(k, v)
end
array = {"Google", "Runoob"}

for key,value in ipairs(array)
do
   print(key, value)
end

8.Java中使用Lua脚本整合redis

1. pom

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.8.1</version>
</dependency>

2. 工具类

package com.*.utils;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class FileUtils {
    //无成员变量 --- 无状态
    public static String getScript(String fileName){
        String path = FileUtils.class.getClassLoader().getResource(fileName).getPath();
        return readFileByLines(path);
    }

	public static String readFileByLines(String fileName) {
        FileInputStream file = null;
        BufferedReader reader = null;
        InputStreamReader inputFileReader = null;
        String content = "";
        String tempString = null;
        try {
            file = new FileInputStream(fileName);
            inputFileReader = new InputStreamReader(file, "utf-8");
            reader = new BufferedReader(inputFileReader);
            // 一次读入一行,直到读入null为文件结束
            while ((tempString = reader.readLine()) != null) {
                content += tempString;
            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e1) {
                }
            }
        }
        return content;
    }
	
	public static void main(String[] args) {
        String path = FileUtils.class.getClassLoader().getResource("unlock.lua").getPath();
		String script = FileUtils.readFileByLines(path);
		System.out.println(script);
	}
}

3. 调用方式

这里是redis实现分布式锁的解锁场景,调用lua脚本保证原子性。

package com.*.lock;

import com.*.utils.FileUtils;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

@Service
public class RedisLock implements Lock {
	
	private static final String  KEY = "LOCK_KEY";
	
	@Resource
	private JedisConnectionFactory factory;

	private ThreadLocal<String> local = new ThreadLocal<>();
	
	
	@Override
	//阻塞式的加锁
	public void lock() {
		//1.尝试加锁
		if(tryLock()){
			return;
		}
		//2.加锁失败,当前任务休眠一段时间
		try {
			Thread.sleep(10);//性能浪费
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		//3.递归调用,再次去抢锁
		lock();
	}



	@Override
	//阻塞式加锁,使用setNx命令返回OK的加锁成功,并生产随机值
	public boolean tryLock() {
		//产生随机值,标识本次锁编号
		String uuid = UUID.randomUUID().toString();
		Jedis jedis = (Jedis) factory.getConnection().getNativeConnection();

		/**
		 * key:我们使用key来当锁
		 * uuid:唯一标识,这个锁是我加的,属于我
		 * NX:设入模式【SET_IF_NOT_EXIST】--仅当key不存在时,本语句的值才设入
		 * PX:给key加有效期
		 * 1000:有效时间为 1 秒
		 */
		String ret = jedis.set(KEY, uuid,"NX","PX",1000);

		//设值成功--抢到了锁
		if("OK".equals(ret)){
			local.set(uuid);//抢锁成功,把锁标识号记录入本线程--- Threadlocal
			return true;
		}

		//key值里面有了,我的uuid未能设入进去,抢锁失败
		return false;
	}

	//正确解锁方式
	public void unlock() {
		//读取lua脚本
		String script = FileUtils.getScript("unlock.lua");
		//获取redis的原始连接
		Jedis jedis = (Jedis) factory.getConnection().getNativeConnection();
		//通过原始连接连接redis执行lua脚本
		jedis.eval(script, Arrays.asList(KEY), Arrays.asList(local.get()));
	}

	//-----------------------------------------------

	@Override
	public Condition newCondition() {
		return null;
	}
	
	@Override
	public boolean tryLock(long time, TimeUnit unit)
			throws InterruptedException {
		return false;
	}

	@Override
	public void lockInterruptibly() throws InterruptedException {
	}

}

5. lua文件

在这里插入图片描述

if redis.call("get",KEYS[1]) == ARGV[1] then 
    return redis.call("del",KEYS[1]) 
else 
    return 0 
end

6. 业务代码

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值