目錄
一、安裝LUA
#二、lua語法簡介
1、註解
1)單行註解
2)多行註解
2、關鍵字
3、變數
1)全域變數
2)局部變數
4、資料型別
1)Lua陣列
2)字串運算
2)while循环
3)break提前退出循环
7、函数
三、Java中执行Lua脚本
1、字符串方式
2、文件方式
3、Luaj概述
四、Redis + Lua(EVAL命令)
1、EVAL命令
首頁 資料庫 Redis Java生態/Redis中怎麼使用Lua腳本

Java生態/Redis中怎麼使用Lua腳本

Jun 02, 2023 pm 10:41 PM
java redis lua

一、安裝LUA

Mac上安裝LUA很簡單,直接使用brew相關指令;

brew install lua
登入後複製

Java生態/Redis中怎麼使用Lua腳本

使用lua -v指令可以看到lua已經安裝完畢。

1)簡單使用

建立一個test.lua文件,內容為:

Java生態/Redis中怎麼使用Lua腳本

執行指令:

lua test.lua
登入後複製

輸出為:

Java生態/Redis中怎麼使用Lua腳本

#二、lua語法簡介

Lua 提供了互動式程式設計與腳本式程式設計:

  • 互動式程式設計:直接在命令列中輸入語法,可以立即執行並查看到執行效果。

  • 腳本是程式設計:編寫腳本文件,然後再執行。

1、註解

lua提供兩種註解方式:單行註解與多行註解

1)單行註解

使用兩個減號;

--

2)多行註解
--[[
 多行注释
 多行注释
 --]]
登入後複製

2、關鍵字

下列為Lua 的保留關鍵字,和Java一樣保留關鍵字不能作為常數或變數。

Java生態/Redis中怎麼使用Lua腳本

3、變數

預設的情況下,定義一個變數都是全域變數;如果要用局部變數需要宣告為local

1)全域變數

全域變數不需要聲明,給一個變數賦值後便創建了這個全域變數;

存取一個沒有初始化的全域變數也不會出錯,只不過會得到結果:nil

Java生態/Redis中怎麼使用Lua腳本

只要將變數賦值為nil,就可以刪除全域變數;換句話說,當且僅當變數為nil時,該變數不存在。

Java生態/Redis中怎麼使用Lua腳本

此外,一般以下劃線開頭連接一串大寫字母的名字(例如 _VERSION)會保留用於 Lua 內部全域變數。

2)局部變數
-- 局部变量赋值
local b=2
登入後複製

4、資料型別

Lua 是動態型別語言,變數不要型別定義,只需要為變數賦值。值可以儲存在變數中,作為參數傳遞或結果傳回。

Lua 中有 8 個基本型別分別為:nil、boolean、number、string、userdata、function、thread 和 table。

Java生態/Redis中怎麼使用Lua腳本

1)Lua陣列

在Lua 陣列中,索引值是從 1 開始,可以指定為從 0 開始。

Java生態/Redis中怎麼使用Lua腳本

2)字串運算
  • #.. 連結兩個字串;

  • string.sub() 用於截取字串;

#
string.sub(s, i [, j])
登入後複製
  • ##s:要截取的字符字串;

  • i:截取開始位置;

  • j:截取結束位置,預設為-1,最後一個字元;

string.find() 用於字串尋找

string.find (str, substr, [init, [plain]])
登入後複製

  • 在一個指定的目標字串str 中搜尋指定的內容substr,如果找到了一個符合的子字串,就會傳回這個子字串的起始索引和結束索引,不存在則回傳nil。

  • init 指定了搜尋的起始位置,預設為 1,可以一個負數,表示從後往前數的字元數。

  • plain 表示是否使用簡單模式,預設為 false,true 只做簡單的查找子字串的操作,false 表示使用正規模式比對。

5、if-else

條件式結果可以是任何值,Lua認為false和nil為假,true和非nil為真。

整體的if-else結構和我們使用的高階語言(Java、GO)類似,差別在於:LUA中的if()表達式滿足之後想要做一些其餘邏輯,需要緊跟

then,並且流程控制以end結尾。

if(xxx) then
    print("xxx")
else if(xx) then
    print("xx")
else
   print("x")
end
登入後複製

6、循環

1)for迴圈
Lua 程式語言中for語句有兩大類別:陣列for迴圈、泛型for迴圈

#1> 數組for循環

語法格式:

for var=exp1,exp2,exp3 do  
    <执行体>  
end
登入後複製

var 從exp1 變化到exp2,每次變化以exp3 為步長遞增var,並執行一次“執行體」。 exp3 是可選的,如果不指定,預設為1。

Java生態/Redis中怎麼使用Lua腳本

2> 泛型for循环

通过一个迭代器函数来遍历所有值,类似 java 中的 foreach 语句;

语法格式:

--打印数组a的所有值  
a = {"one", "two", "three"}
for i, v in ipairs(a) do
    print(i, v)
end
登入後複製
  • i 是数组索引值,v 是对应索引的数组元素值。

  • ipairs是Lua提供的一个迭代器函数,用来迭代数组。

Java生態/Redis中怎麼使用Lua腳本

2)while循环

while 循环语句在判断条件为 true 时会重复执行循环体语句。

语法格式:

while(condition)
do
   statements
end
登入後複製
  • statements(循环体语句) 可以是一条或多条语句,condition(条件) 可以是任意表达式;

  • 在 condition(条件) 为 true 时执行循环体语句。

Java生態/Redis中怎麼使用Lua腳本

3)break提前退出循环

和Java中的break一个作用,用于退出当前循环或语句;

7、函数

在Lua中,函数是对语句和表达式进行抽象的主要方法。类似于Java中的方法。

Lua 函数主要有两种用途:

  • 完成指定的任务,这种情况下函数作为调用语句使用;

  • 计算并返回值,这种情况下函数作为赋值语句的表达式使用;

函数的编写方式如下:

--[[ 函数返回两个值的最大值 --]]
function max(num1, num2)
   if (num1 > num2) then
      result = num1;
   else
      result = num2;
   end
   return result; 
end
-- 调用函数
print("两值比较最大值为 ",max(10,4))
print("两值比较最大值为 ",max(5,6))
登入後複製

Java生態/Redis中怎麼使用Lua腳本

三、Java中执行Lua脚本

Java中执行Lua脚本有两种方式:字符串的方式、文件的方式;

Java中想要执行LUA脚本,首先需要在pom中引入相关依赖:

<dependency>
    <groupId>org.luaj</groupId>
    <artifactId>luaj-jse</artifactId>
    <version>3.0.1</version>
</dependency>
登入後複製

1、字符串方式

对于简单的lua脚本,可以直接用java字符串写;

package com.saint.base.lua;

import org.luaj.vm2.Globals;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.jse.JsePlatform;

public class LuaString {
    public static void main(String[] args) {
        String luaStr = "print &#39;Saint is best man&#39;";
        Globals globals = JsePlatform.standardGlobals();
        LuaValue luaValue = globals.load(luaStr);
        luaValue.call();
    }
}
登入後複製

控制台输出:

Java生態/Redis中怎麼使用Lua腳本

2、文件方式

对于一些比较常用的、复杂的脚本可以选择存放在文件中,在Java中再调用lua文件;

package com.saint.base.lua;

import org.luaj.vm2.Globals;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.jse.JsePlatform;

import java.io.FileNotFoundException;

public class LuaFile {
    public static void main(String[] args) throws FileNotFoundException {
        // lua脚本的文件路径
        String luaPath = "/xxxx/javaTest.lua";
        Globals globals = JsePlatform.standardGlobals();
        //加载脚本文件login.lua,并编译
        globals.loadfile(luaPath).call();
        LuaValue func1 = globals.get(LuaValue.valueOf("print1"));
        func1.call();

        LuaValue func2 = globals.get(LuaValue.valueOf("print2"));
        String luaResp = func2.call(LuaValue.valueOf("saint-input-param")).toString();
        System.out.println("lua file return is : " + luaResp);
    }
}
登入後複製

lua脚本文件:

Java生態/Redis中怎麼使用Lua腳本

控制台输出:

Java生態/Redis中怎麼使用Lua腳本

3、Luaj概述

Luaj在包装执行具体的Lua代码时, 有三种不同的模式;

  • 纯脚本解析执行(不选用任何Compiler)

  • To Lua字节码(LuaC, lua-to-lua-bytecode compiler)(默认选用)

  • To Java字节码(LuaJC, lua-to-java-bytecode compiler)

Luaj中的Globals对象不是线程安全的, 因此最佳实践是每个线程一个Globals对象。

事实上, 可以采用ThreadLocal的方式来存储该对象。

2)性能问题

Lua脚本在JAVA中运行,相比于直接运行Java代码会慢很多,大约1000倍。

四、Redis + Lua(EVAL命令)

在使用Redisson、Jedis+Lua时,我们可以通过redis客户端集成的、手写的LUA脚本来保证一系列命令在Redis中可以"原子执行"。

在redis执行lua脚本时,相当于一个redis级别的锁,不能执行其他操作,类似于原子操作,这也是redisson实现的一个关键点。

比如Redisson中的lua脚本:

Java生態/Redis中怎麼使用Lua腳本

Redisson如何实现分布式锁,可以看文章:https://www.yisu.com/article/277312.htm

lua脚本中有如下几个概念:

  • redis.call():执行redis命令。

  • KEYS[n]:指脚本中第n个参数,比如KEYS[1]指脚本中的第一个参数。

  • ARGV[n]:指脚本中第n个参数的值,比如ARGV[1]指脚本中的第一个参数的值。

  • 返回值中nil与false同一个意思。

1、EVAL命令

redis2.6.0版本起 采用内置的Lua解释器 通过EVAL命令去执行脚本;

redis中的EVAL命令可以用于执行一段lua代码。命令格式如下:

Java生態/Redis中怎麼使用Lua腳本

  • 第一个参数script:表示lua脚本的内容;

  • 第二参数numkeys:表示有多少个键值对。

  • 其余参数:先把numkeys个key列出来,再把numkeys个arg列出来。

Lua脚本中可以使用2个函数调用redis命令;

  • redis.call()

  • redis.pcall()

redis.call()与redis.pcall()相似,二者唯一不同之处:

  • 如果执行的redis命令执行失败,redis.call()将产生一个Lua error,从而迫使EVAL命令返回一个错误给命令的调用者;

  • 然而redis.pcall()将会捕捉这个错误,并返回代表这个错误的Lua表。

有那么一段逻辑;

  • 如果Redis某个key的整数值 和 某个value相等,则将key对应的整数值 + 1000;否则将key的值设置为9999;

lua脚本执行命令如下:

EVAL "if redis.call(&#39;get&#39;, KEYS[1]) == ARGV[1] then return redis.call(&#39;INCRBY&#39;, KEYS[1], 1000); else redis.call(&#39;set&#39;, KEYS[1], 9999); return nil; end;" 1 test 100
登入後複製

根据test值的不同,不同的执行结果如下:

Java生態/Redis中怎麼使用Lua腳本

以上是Java生態/Redis中怎麼使用Lua腳本的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1666
14
CakePHP 教程
1425
52
Laravel 教程
1327
25
PHP教程
1273
29
C# 教程
1252
24
如何利用Redis緩存方案高效實現產品排行榜列表的需求? 如何利用Redis緩存方案高效實現產品排行榜列表的需求? Apr 19, 2025 pm 11:36 PM

Redis緩存方案如何實現產品排行榜列表的需求?在開發過程中,我們常常需要處理排行榜的需求,例如展示一個�...

REDIS的角色:探索數據存儲和管理功能 REDIS的角色:探索數據存儲和管理功能 Apr 22, 2025 am 12:10 AM

Redis在數據存儲和管理中扮演著關鍵角色,通過其多種數據結構和持久化機製成為現代應用的核心。 1)Redis支持字符串、列表、集合、有序集合和哈希表等數據結構,適用於緩存和復雜業務邏輯。 2)通過RDB和AOF兩種持久化方式,Redis確保數據的可靠存儲和快速恢復。

Spring Boot中OAuth2Authorization對象Redis緩存失敗怎麼辦? Spring Boot中OAuth2Authorization對象Redis緩存失敗怎麼辦? Apr 19, 2025 pm 08:03 PM

SpringBoot中使用Redis緩存OAuth2Authorization對像在SpringBoot應用中,使用SpringSecurityOAuth2AuthorizationServer...

REDIS:了解其架構和目的 REDIS:了解其架構和目的 Apr 26, 2025 am 12:11 AM

Redis是一种内存数据结构存储系统,主要用作数据库、缓存和消息代理。它的核心特点包括单线程模型、I/O多路复用、持久化机制、复制与集群功能。Redis在实际应用中常用于缓存、会话存储和消息队列,通过选择合适的数据结构、使用管道和事务、以及进行监控和调优,可以显著提升其性能。

使用RedisTemplate進行批量查詢時,為什麼返回值會為空? 使用RedisTemplate進行批量查詢時,為什麼返回值會為空? Apr 19, 2025 pm 10:15 PM

使用RedisTemplate進行批量查詢時為何返回值為空?在使用RedisTemplate進行批量查詢操作時,可能會遇到返回的結果�...

為什麼redisTemplate.opsForList().leftPop()方法不支持傳入參數來一次性彈出多個值? 為什麼redisTemplate.opsForList().leftPop()方法不支持傳入參數來一次性彈出多個值? Apr 19, 2025 pm 10:27 PM

關於RedisTemplate.opsForList().leftPop()不支持傳個數的原因在使用Redis時,很多開發者會遇到一個問題:為什麼redisTempl...

在多節點環境下,如何確保Spring Boot的@Scheduled定時任務只在一個節點上執行? 在多節點環境下,如何確保Spring Boot的@Scheduled定時任務只在一個節點上執行? Apr 19, 2025 pm 10:57 PM

SpringBoot定時任務在多節點環境下的優化方案在開發Spring...

作曲家:通過AI的幫助開發PHP 作曲家:通過AI的幫助開發PHP Apr 29, 2025 am 12:27 AM

AI可以幫助優化Composer的使用,具體方法包括:1.依賴管理優化:AI分析依賴關係,建議最佳版本組合,減少衝突。 2.自動化代碼生成:AI生成符合最佳實踐的composer.json文件。 3.代碼質量提升:AI檢測潛在問題,提供優化建議,提高代碼質量。這些方法通過機器學習和自然語言處理技術實現,幫助開發者提高效率和代碼質量。

See all articles