redis與lua

內容大綱php

redis裏使用eval和evalshagit

redis管理Lua腳本 redis

php裏使用redis的lua腳本centos

在redis裏使用lua腳本的好處網絡

1.Lua腳本在Redis中是原子執行的,執行過程當中間不會插入其餘命令
2.Lua腳本能夠幫助開發和運維人員創造出本身定製的命令,並能夠將這些命令常駐在Redis內存中,實現複用的效果。
3.Lua腳本能夠將多條命令一次性打包,有效地減小網絡開銷數據結構

在redis中運維

eval的語法格式
EVAL script numkeys key [key ...] arg [arg ...]
其中:
<1> script: 你的lua腳本
<2> numkeys: key的個數
<3> key: redis中各類數據結構的替代符號
<4> arg: 你的自定義參數tcp

eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 username age hk 20
第一個參數的字符串是script,也就是lua腳本,2表示keys的個數,KEYS[1] 就是username的佔位符, KEYS[2]就是
age的佔位符,ARGV[1]就是jk的佔位符,ARGV[2]就是20的佔位符,以此類推,因此最後的結果應該就是:{return username age hk 20}ide

其中要要讀寫的鍵名應該做爲key參數,其它的數據都做爲arg參數
eval命令依據第二個參數將後面的全部參數分別存入腳本中KEYS和ARGV兩個表類型的全局變量。
當腳本不須要任何參數時也不能省略這個參數(設爲0)ui

在cli中執行

250:0>eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 username age hk 20
 1)  "username"
 2)  "age"
 3)  "hk"
 4)  "20"

執行Lua腳本文件

redis-cli --eval keys.lua k1 k2 , v1 v2

key和value用一個逗號隔開

keys.lua

return {
KEYS,
type(KEYS),
'-----',
ARGV,
type(ARGV)
}
[root@centos1 lua]# redis-cli --eval keys.lua k1 k2 , v1 v2
1) 1) "k1"
   2) "k2"
2) "table"
3) "-----"
4) 1) "v1"
   2) "v2"
5) "table"

evalsha

將Lua腳本加載到Redis服務端,獲得該腳本的sha1校驗和,evalsha命令使用sha1做爲參數能夠直接執行對應的Lua腳本,
避免每次發送Lua腳本的開銷。這樣客戶端就不須要每次執行腳本內容,而腳本也會常駐在服務端,腳本內容獲得了複用
加載腳本: script load命令能夠將腳本內容加載到Redis內存中

hmgetall.lua  獲取多個hash key的值

--獲取指定的多個hash key

local result={}
for i,v in ipairs(KEYS) do
    result[i]=redis.call('HGETALL',v)
end
return result

[root@centos1 redis-lua]# redis-cli script load "$(cat hmgetall.lua)"
"032f22e507d134837f1c948f5b4f6b979b2e8beb"
獲得sha1的值
在redis裏執行腳本
evalsha 腳本sha1值 key個數 key列表 參數列表
evalsha 032f22e507d134837f1c948f5b4f6b979b2e8beb 2 user:1 user:2 0

127.0.0.1:6379> evalsha 032f22e507d134837f1c948f5b4f6b979b2e8beb 2 user:1 user:2 
1) 1) "name"
   2) "hk"
   3) "age"
   4) "20"
2) 1) "name"
   2) "hk2"
   3) "age"
   4) "22"

Redis管理Lua腳本
1.script load
此命令用於將Lua腳本加載到Redis內存中
2.script exists
scripts exists sha1 [sha1 …]
此命令用於判斷sha1是否已經加載到Redis內存中
3.script flush
此命令用於清除Redis內存已經加載的全部Lua腳本,在執行script flush後,sha1不復存在 
4.script kill
此命令用於殺掉正在執行的Lua腳本

爲了防止某個腳本執行時間過長致使redis沒法提供服務
redis提供lua-time-limit 參數限制腳本的最長運行時間,默認爲5秒
當腳本運行超過這一限制後,redis將開始接收其它命令但不會執行(以確認腳本的原子性,由於此時腳本並無終止),而是返回busy 錯誤
打開2個redis客戶端
redis A> eval "while true do end" 0
redis B中
127.0.0.1:6379> keys *
(error) BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE.
此時redis雖然能夠接收任何命令,但實際會執行的只有2個 SCRIPT KILL or SHUTDOWN NOSAVE
127.0.0.1:6379> script kill
OK
須要注意的是 若是當執行的是修改操做,則 SCRIPT KILL 命令不會終止腳本的運行以防止腳本只執行了一部分(違背原子性的要求)
redis A>eval "redis.call('set','name','hk') while true do end" 0
redis B裏

127.0.0.1:6379> keys *
(error) BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE.
127.0.0.1:6379> script kill
(error) UNKILLABLE Sorry the script already executed write commands against the dataset. You can either wait the script termination or kill the server in a hard way using the SHUTDOWN NOSAVE command.

此時只能 SHUTDOWN NOSAVE
SHUTDOWN NOSAVE 不會進行持久化的操做 與 SHUTDOWN 的區別

php裏使用redis的lua腳本

lua.php

<?php
require "./vendor/autoload.php";

class HMGetAll extends \Predis\Command\ScriptCommand{

    public function getKeysCount()
    {
        return false;
    }
    public function getScript(){
        return
        <<<LUA
        local result = {}
        for i ,v in ipairs(ARGV) do
            result[i] =redis.call('HGETALL',v)
        end
        return result
LUA;

    }
}
$client= new \Predis\Client(
    [
        'scheme'=>'tcp',
        'host' => '192.168.0.250',
        'port' => 6379,
        ]
);
//定義hmgetall命令
$client->getProfile()->defineCommand("hmgetall",'HMGetAll');

var_dump($client->hgetall('user:1'));
var_dump($client->hgetall('user:2'));
//執行hmgetall

$value=$client->hmgetall('user:1','user:2');
var_dump($value);

結果相似

D:\wamp64\www\cnblogs\lua\php\lua.php:32:
array (size=2)
  'name' => string 'hk' (length=2)
  'age' => string '20' (length=2)
D:\wamp64\www\cnblogs\lua\php\lua.php:33:
array (size=2)
  'name' => string 'hk2' (length=3)
  'age' => string '22' (length=2)
D:\wamp64\www\cnblogs\lua\php\lua.php:37:
array (size=2)
  0 => 
    array (size=4)
      0 => string 'name' (length=4)
      1 => string 'hk' (length=2)
      2 => string 'age' (length=3)
      3 => string '20' (length=2)
  1 => 
    array (size=4)
      0 => string 'name' (length=4)
      1 => string 'hk2' (length=3)
      2 => string 'age' (length=3)
      3 => string '22' (length=2)
View Code

參考redis入門指南(書中這塊有錯誤 應該是ARGV而不是循環KEYS) 

詳細代碼見  https://gitee.com/hk/cnblogs/tree/master/lua/php

相關文章
相關標籤/搜索