java akiba,java使用jeids实现redis2.6的脚本执行
代碼:
https://github.com/viakiba/redis
import static org.junit.Assert.*;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import redis.clients.jedis.Jedis;
/**
* @description:
* Lua Script(腳本)
* 從 Redis 2.6.0 版本開始,通過內置的 Lua 5.1解釋器,可以使用 EVAL 命令對 Lua 腳本進行求值。
* 參考:http://redisdoc.com/script/index.html
* 主要演示命令:EVAL,EVALSHA,SCRIPT EXISTS,SCRIPT FLUSH,SCRIPT KILL,SCRIPT LOAD
*
* @author viakiba
* @date 2017年8月17日
*/
public class App27 {
static interface RedisConfig {
public final static String HOST = "127.0.0.1";
public final static int PORT = 6379;
}
/**
* @description: 測試連接是否通過
* @author: viakiba
* @throws Exception
*/
@Test
public void test1() throws Exception {
//連接測試是否通過
Jedis jedis = new Jedis(RedisConfig.HOST,RedisConfig.PORT);
System.out.println(jedis.ping());//pong則通過
}
/**
* @description:EVAL/EVALSHA
* 僅提供一個建議示范
* 需要lua知識
* http://luadist.org/
* 參考:
* http://redisdoc.com/script/eval.html
* @author: viakiba
* @throws Exception
*/
@Test
public void test2() throws Exception {
Jedis jedis = new Jedis(RedisConfig.HOST,RedisConfig.PORT);
/*
* EVAL:
* EVAL script numkeys key [key ...] arg [arg ...]
* numkeys 參數用于指定鍵名參數的個數。
* 鍵名參數 key [key ...] 從 EVAL 的第三個參數開始算起,表示在腳本中所用到的那些 Redis 鍵(key),
* 這些鍵名參數可以在 Lua 中通過全局變量 KEYS 數組,用 1 為基址的形式訪問( KEYS[1] , KEYS[2] ,以此類推)。
* 在命令的最后,那些不是鍵名參數的附加參數 arg [arg ...] ,可以在 Lua 中通過全局變量 ARGV 數組訪問,
* 訪問的形式和 KEYS 變量類似( ARGV[1] 、 ARGV[2] ,諸如此類)。
*/
//java 執行 命令: eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 k1 k2 a b
//System.out.println(jedis.ping());
//String str1 = "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}";
//Object eval1 = jedis.eval(str1, 2,"k1","k2","a1","a2");
//System.out.println(eval1);
//List a = (ArrayList) eval1;
//System.out.println(a.get(1));
/*
在 Lua 腳本中,可以使用兩個不同函數來執行 Redis 命令,它們分別是:redis.call(),redis.pcall()
這兩個函數的唯一區別在于它們使用不同的方式處理執行命令所產生的錯誤,在后面的『錯誤處理』部分會講到這一點。
redis.call()
當 redis.call() 在執行命令的過程中發生錯誤時,腳本會停止執行,并返回一個腳本錯誤,錯誤的輸出信息會說明錯誤造成的原因,例如:
lpush foo2 a
eval "return redis.call('get', 'foo2')" 0
(error) ERR Error running script (call to f_9f940e4b715e855705c618305be7aeed2c4d
572f): @user_script:1: WRONGTYPE Operation against a key holding the wrong kind
of value
redis.pcall()
redis.pcall() 出錯時并不引發(raise)錯誤,而是返回一個帶 err 域的 Lua 表(table),用于表示錯誤,例如:
lpush foo3 a
EVAL "return redis.pcall('get', 'foo3')" 0
(error) WRONGTYPE Operation against a key holding the wrong kind of value
*/
//call
//System.out.println(jedis.ping());
//String str1 = "return redis.call('set',KEYS[1],'bar')";//設置鍵k1的值為bar
//Object eval1 = jedis.eval(str1, 1,"k1");
//System.out.println(eval1);
//System.out.println(jedis.get("k1"));//查看執行情況
//pcall
System.out.println(jedis.ping());
String str1 = "return redis.pcall('set',KEYS[1],'bar')";//設置鍵k1的值為bar
Object eval1 = jedis.eval(str1, 1,"k1");
System.out.println(eval1);
System.out.println(jedis.get("k1"));//查看執行情況
}
/**
* @description:
* EVALSHA
* 根據給定的 sha1 校驗碼,對緩存在服務器中的腳本進行求值。
* 將腳本緩存到服務器的操作可以通過 SCRIPT LOAD 命令進行。
* 這個命令的其他地方,比如參數的傳入方式,都和 EVAL 命令一樣。
* SCRIPT LOAD:
* 將腳本 script 添加到腳本緩存中,但并不立即執行這個腳本。
* EVAL 命令也會將腳本添加到腳本緩存中,但是它會立即對輸入的腳本進行求值。
* 如果給定的腳本已經在緩存里面了,那么不做動作。
* 在腳本被加入到緩存之后,通過 EVALSHA 命令,可以使用腳本的 SHA1 校驗和來調用這個腳本。
* 腳本可以在緩存中保留無限長的時間,直到執行 SCRIPT FLUSH 為止。
* SCRIPT FLUSH:
* 清除所有 Lua 腳本緩存。
* @author: viakiba
* @throws Exception
*/
@Test
public void test3() throws Exception {
Jedis jedis = new Jedis(RedisConfig.HOST,RedisConfig.PORT);
jedis.ping();
//System.out.println(jedis.scriptLoad("return 'hello world'"));
System.out.println(jedis.evalsha("5332031c6b470dc5a0dd9b4bf2030dea6d65de91",0));
byte[] scriptFlush = jedis.scriptFlush();
System.out.println(new String(scriptFlush,0,scriptFlush.length));
//System.out.println(jedis.evalsha("5332031c6b470dc5a0dd9b4bf2030dea6d65de91",0));//在執行就會報錯了 因為所有 Lua 腳本緩存已經被清除了
}
/**
* @description: SCRIPT EXISTS
* 給定一個或多個腳本的 SHA1 校驗和,返回一個包含 0 和 1 的列表,表示校驗和所指定的腳本是否已經被保存在緩存當中
* 例如:
* SCRIPT LOAD "return 'hello moto'"
* SCRIPT EXISTS 232fd51614574cf0867b83d384a5e898cfd24e5a
* SCRIPT FLUSH
* SCRIPT EXISTS 232fd51614574cf0867b83d384a5e898cfd24e5a
* @author: viakiba
* @throws Exception
*/
@Test
public void test4() throws Exception {
Jedis jedis = new Jedis(RedisConfig.HOST,RedisConfig.PORT);
jedis.ping();
System.out.println(jedis.scriptLoad("return 'hello moto'"));
System.out.println(jedis.scriptExists("232fd51614574cf0867b83d384a5e898cfd24e5a"));
System.out.println(new String(jedis.scriptFlush()));
System.out.println(jedis.scriptExists("232fd51614574cf0867b83d384a5e898cfd24e5a"));
}
/**
* @description: SCRIPT KILL
* 殺死當前正在運行的 Lua 腳本,當且僅當這個腳本沒有執行過任何寫操作時,這個命令才生效。
* 這個命令主要用于終止運行時間過長的腳本,比如一個因為 BUG 而發生無限 loop 的腳本,諸如此類。
* SCRIPT KILL 執行之后,當前正在運行的腳本會被殺死,執行這個腳本的客戶端會從 EVAL 命令的阻塞當中退出,并收到一個錯誤作為返回值。
* 另一方面,假如當前正在運行的腳本已經執行過寫操作,那么即使執行 SCRIPT KILL ,也無法將它殺死,因為這是違反 Lua 腳本的原子性執行原則的。
* 在這種情況下,唯一可行的辦法是使用 SHUTDOWN NOSAVE 命令,通過停止整個 Redis 進程來停止腳本的運行,并防止不完整(half-written)的信息被寫入數據庫中。
* @author: viakiba
* @throws Exception
*/
@Test
public void test5() throws Exception {
Jedis jedis = new Jedis(RedisConfig.HOST,RedisConfig.PORT);
jedis.ping();
try{
System.out.println(new String(jedis.scriptKill()));
//成功殺死腳本時 返回ok
//處理異常 NOTBUSY No scripts in execution right now.
}catch(Exception e){
e.printStackTrace();
}
}
}
總結
以上是生活随笔為你收集整理的java akiba,java使用jeids实现redis2.6的脚本执行的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 厦航女飞行员招飞标准是什么?
- 下一篇: java删除目录以及目录下文件,java