redisのluaスクリプト


目次
eval
構文

luaでredis関数を実行する
redis.call()
redis.pcall()
なぜ正しい形式でキーを渡すのですか?
変換ルール
redisからlua
牙列缺损
スクリプトの原子性
evalsha
構文
evalshaコマンドは、次のように表示されます.
スクリプトキャッシュ
スクリプトキャッシュのリフレッシュ
scriptコマンド
純粋なスクリプト関数
グローバル変数の保護
ライブラリ
loglevel値
砂箱と最大実行時間
最大実行時間に達すると、次の操作が実行されます.
パイプラインコンテキスト(context)のevalsha
script load 
構文
script exists
構文
script flush
構文
script kill
構文
公式文書を参照:http://redisdoc.com/script/index.html
eval
redisは2.6.0バージョンから、lua解釈器を内蔵することでevalを使用してluaスクリプトを評価できます.
構文
eval script numkeys key [key...] arg[arg...]

script:lua 5.1スクリプトプログラムはredisサーバコンテキストで実行され、このスクリプトは変わらずlua関数として定義されるべきではありません.
numkeys:キー名パラメータの個数を指定する
key[key...]:evalのディサンパラメータから計算すると、luaでグローバル変数KEYS配列を介して1をベースとしてアクセスできるスクリプトで使用されるredisキー(key)を表す.
KEYS[1],KEYS[2]...

arg[arg...]:追加パラメータは、luaでグローバル変数ARGV配列方式で
ARGV[1], ARGV[2]...

> eval "return {KEYS[1], KEYS[2], ARGV[1], ARGV[2]}" 2 key1 key2 arg1 arg2
1)"key1"
2)"key2"
3)"arg1"
4)"arg2"

「return{KEYS[1],KEYS[2],ARGV[1],ARGV[2]}」は評価されたluaスクリプトであり、「2」は簡明なパラメータの数を指定し、key 1とkey 2はキー名パラメータであり、それぞれKEYS[1],KEYS[2]を使用してアクセスし、arg 1とarg 2は追加パラメータであり、ARGV[1]とARGV[2]を介してアクセスする.
luaでredis関数を実行する
redis.call()
コマンドの実行中にエラーが発生すると、スクリプトは実行を停止し、スクリプトエラーを返します.エラーの情報はエラーの原因を示します.
redis.pcall()
コマンドの実行中にエラーが発生することはなく、エラーを表すためにerrドメイン付きluaテーブル(table)を返します.
> eval "return redis.call('set', KEYS[1], 'bar')" 1 foo  //   
> eval "return redis.call('set', 'foo', 'bar')" 0 //   。          KEYS     

なぜ正しい形式でキーを渡すのですか?
evalコマンドだけでなく、すべてのredisコマンドは、実行前に分析され、コマンドがどのキーを操作するかを決定します.
evalコマンドでは、分析が正常に実行されるように、正しい形式でキーを渡す必要があります.
それ以外に、redisクラスタが正しいクラスタノードにリクエストを送信できることを確認します.
luaデータ型とredisデータ型の変換
redisを通過するとcall()またはredis.pcall()がredisコマンドを実行すると、コマンドの戻り値がluaデータ構造に変換されます.
luaスクリプトがredisに内蔵された解釈器で実行されると、luaスクリプトの戻り値はredisプロトコル(protocol)に変換され、evalによってクライアントに返されます.
変換ルール
redisからlua
Redis integer reply -> Lua number / Redis       Lua   
Redis bulk reply -> Lua string / Redis bulk       Lua    
Redis multi bulk reply -> Lua table (may have other Redis data types nested) / Redis    bulk       Lua  ,          Redis     
Redis status reply -> Lua table with a single ok field containing the status / Redis         Lua  ,    ok         
Redis error reply -> Lua table with a single err field containing the error / Redis         Lua  ,    err         
Redis Nil bulk reply and Nil multi bulk reply -> Lua false boolean type / Redis   Nil     Nil         Lua      false

牙列缺损
Lua number -> Redis integer reply / Lua       Redis   
Lua string -> Redis bulk reply / Lua        Redis bulk   
Lua table (array) -> Redis multi bulk reply / Lua  (  )    Redis    bulk   
Lua table with a single ok field -> Redis status reply /       ok    Lua  ,    Redis     
Lua table with a single err field -> Redis error reply /       err    Lua  ,    Redis     
Lua boolean false -> Redis Nil bulk reply / Lua      false     Redis   Nil bulk   

luaからredisへの追加のルールは、redisからluaへの変換に対応していません.
Lua boolean true -> Redis integer reply with value of 1 / Lua     true     Redis        1

スクリプトの原子性
redisは、単一のlua解釈器を使用してすべてのスクリプトを実行し、あるスクリプトが実行中である場合、他のスクリプトまたはredisコマンドが実行されないことを保証します.
もちろん、遅いスクリプトを実行している場合は、サーバが忙しいために他のコマンドを実行できない可能性があります.
evalsha
evalコマンドは、スクリプトを実行するたびにスクリプトボディ(script body)を1回送信するように要求します.redisは内部キャッシュメカニズムによって、スクリプトを毎回再コンパイルすることはありません.スクリプトボディを送信するたびに、帯域幅が消費されます.
帯域幅消費を減らすためにredisはevalshaコマンドを実現し,evalと同様にスクリプトの評価に機能するが,最初のパラメータはスクリプトではなくスクリプトのsha 1チェックサム(sum)である.
構文
evalsha sha1 numkeys key[key ...] arg[arg ...]

evalshaコマンドは、次のように表示されます.
1.サーバが指定したsha 1チェックサムと指定したスクリプトを覚えている場合、このスクリプトを実行します.
2.サーバが指定したsha 1チェックサムと指定したスクリプトを覚えていない場合、evalshaの代わりにevalを使用するようにユーザーに注意する特殊なエラーが返されます.
`NOSCRIPT` No matching script. Please use [EVAL]

スクリプトキャッシュ
redisは、実行されたすべてのスクリプトがスクリプトキャッシュに永続的に保存されることを保証します.これは、evalコマンドがredisインスタンス上でスクリプトを正常に実行した後、このスクリプトに対するすべてのevalshaコマンドが正常に実行されることを意味します.
スクリプトキャッシュのリフレッシュ
//             
script flush 

このコマンドは、通常、クラウドコンピューティング中にredisインスタンスが他のクライアントまたは他のアプリケーションのインスタンスに変更された場合にのみ実行されます.
キャッシュはメモリの問題が発生せずに長時間保存でき、体積が小さく、数が少ない.
キャッシュ・スクリプトを削除しないメリット:
redisと永続化リンクを維持するプログラムでは、一度実行したスクリプトがメモリに保持されるため、スクリプトが見つからずにエラーが発生する心配がなく、パイプラインでevalshaコマンドを使用することができます.
scriptコマンド
スクリプトサブシステムの制御に使用
//         
script flush
//           ,               
script exists sha1[sha1 ...]
//            ,       
script load script
// kill       
script kill

純粋なスクリプト関数
スクリプトは純粋な関数として書かれるべきです.スクリプトのプロパティ:
同じデータセット入力に対して、同じパラメータが与えられると、スクリプト実行のredis書き込みコマンドは常に同じであり、スクリプト実行の曹祖は隠れたデータに依存することができず、スクリプト実行中、スクリプトが異なる実行時期の間に変更可能な状態に依存することができず、I/Oデバイスからの外部入力にも依存することができない.
システム時間の使用、randomkeyランダムコマンドの呼び出し、lua乱数の使用など、スクリプトの評価が毎回同じ結果にならないようにします.
このプロパティを満たすためにredisは次の作業を行います.
1.lua                   
2.redis       ,         :             ,          redis  
3.   lua                 ,             lua               。
4. lua         math.random math.randomseed    ,             ,       seed 

グローバル変数の保護
不要なデータがlua環境に漏洩しないように、luaスクリプトではグローバル=変数の作成は許可されません.1つのスクリプトが複数回の実行間に何らかの状態を維持する必要がある場合は、redis keyを使用して状態保存を行う必要があります.
luaのdebugツールや他の施設、例えば印刷alterがグローバル保護を実現するために使用するmeta tableは、グローバル変数保護を実現するために使用することができる.
スクリプトにluaグローバルステータスが混入すると、aof永続化とレプリケーションは保証されませんので、スクリプトでグローバル変数を使用しないでください.
グローバル変数の導入を回避:スクリプトで使用されるすべての変数はlocalキーを使用してローカル変数として定義されます.
ライブラリ
redis内蔵lua解釈器は以下のluaライブラリをロードしました
base, table,string, math,debug,cjson,cmsgpack
cjsonライブラリはluaにjsonデータを非常に迅速に処理させることができる.
各redisインスタンスは、これらのライブラリがロードされることを保証し、各redisスクリプトが実行環境と同じであることを保証します.
スクリプトを使用してredisログを記録する
luaスクリプトではredisを使用します.logはredisログを記録します.
//  lua     redis  
redis.log(loglevel, message)

loglevel値
redis.LOG_DEBUG
redis.LOG_VERBOSE
redis.LOG_NOTICE
redis.LOG_WARNING

これらのログ・レベルは、標準のredisログ・レベルに対応します.
砂箱と最大実行時間
スクリプトは、パラメータの転送とredisデータの処理にのみ使用され、ファイルシステムなどの外部システムにアクセスしたり、システム呼び出しを実行したりする必要はありません.
最大実行時間制限、デフォルトは5秒です.
通常、正常に実行されるスクリプトは、通常、数分の数ミリ秒で完了します.
この時間制限は主にプログラミングエラーを防止するために無限ループをもたらす.
最大実行時間の長さはredis.confはlua-time-limit制御(ミリ秒単位)を得る.次のコマンドを使用して変更することもできます.
config get parameter //       
config set parameter value //       

スクリプトが最大実行時間に達すると、redisは終了しません.redisはスクリプトの原子性を保証する必要がありますが、スクリプトの実行を途中で停止することは、未処理のデータがデータセットdata setに残る可能性があることを意味します.
最大実行時間に達すると、次の操作が実行されます.
1. redis            
2. redis                ,    script kill shutdown nosave        ,      ,redis      busy  。
3.       script kill             kill,          ,kill           
4.             ,          :shutdown nosave,                   。

パイプラインコンテキスト(context)のevalsha
パイプラインリクエストの上希望でevalshaコマンドを使用する場合は、パイプラインでコマンドの実行順序を保証する必要があるため、注意してください.
流水ラインでevalshaコマンドでnoscriptエラーが発生すると、この流水ラインは二度と再実行できません.そうしないと、コマンドの実行順序が狂ってしまいます.
この問題を防止するために、クライアントは次のいずれかの措置を実装する必要があります.
1.         eval  
2.              ,     eval  ,   script exists sha1[sha1...]                         。                  ,        eval    evalsha  ,                  script load script     

script load 
構文
//  script       ,      。              script sha1   
script load script

指定されたスクリプトがキャッシュにすでに存在する場合は、動作しません.
スクリプトがキャッシュに追加されると、evalshaコマンドにより、スクリプトのsha 1チェックサムを使用してスクリプトを呼び出すことができます.
//  script       ,     
eval script numksys key[key ...] arg[arg ...]

script exists
構文
script exists sha1 [sha1 ...]

1つ以上のスクリプトのsha 1チェックサムが与えられ、チェックサムが指定したスクリプトがキャッシュに保存されているかどうかを示す0(スクリプトはキャッシュに存在しない)と1(スクリプトはファンチュンに存在する)を含むリストが返されます.
script flush
構文
script flush //     Lua    

script kill
構文
script kill //           kill。      OK,          

このスクリプトを実行するクライアントはeval script numkeys key[key...]arg[arg ...]コマンドのブロックから終了し、戻り値としてエラーが受信されました.
現在実行中のスクリプトが書き込み操作を実行している場合は、luaスクリプトの原子的実行の原則に違反しているため、killを削除することはできません.この場合、shutdown nosaveを使用して、redisプロセス全体を停止することによってスクリプトの実行を停止し、不完全な情報がデータベースに書き込まれることを防止する唯一の方法があります.