ホームページ データベース Redis Go言語のLuaスクリプトでRedisを操作する方法

Go言語のLuaスクリプトでRedisを操作する方法

May 27, 2023 pm 07:52 PM
redis lua 言語を移動

はじめに

私の基本ライブラリの 1 つで Redis との通信コストを削減するために、一連の操作を LUA スクリプトにカプセル化し、Redis が提供する EVAL コマンドを使用しました。操作を簡素化するため。

EVAL が提供できる機能:

  • LUA スクリプトで複数の操作をカプセル化できます。複数の Redis 命令がある場合、カプセル化その後、すべてのパラメーターを一度に Redis に送信して結果を取得します。

  • Redis は、Lua スクリプトの実行中に他のコマンドが挿入および実行されないことを保証し、アトミック性を提供します。

  • Redis は、スクリプトの SHA 値に従ってスクリプトをキャッシュします。キャッシュされたスクリプトは、Lua コードを再度送信する必要がなく、通信コストが削減されます。さらに、独自のコードで Lua スクリプトを変更すると、Redis の実行時にも最新のコードが使用されます。

「github.com/go-redis/redis」などの一般的な Go ライブラリをインポートして、次のコードを実装します。

Lua スクリプトの生成

// KEYS: key for record
// ARGV: fieldName, currentUnixTimestamp, recordTTL
// Update expire field of record key to current timestamp, and renew key expiration
var updateRecordExpireScript = redis.NewScript(`
redis.call("EXPIRE", KEYS[1], ARGV[3])
redis.call("HSET", KEYS[1], ARGV[1], ARGV[2])
return 1
`)
ログイン後にコピー

この変数が作成されると、Lua コードは実行されず、既存の Redis 接続が必要ありません。

Redis が提供する Lua スクリプト サポートには、デフォルトで KEYS と ARGV という 2 つの配列があります。KEYS は、スクリプトの実行時に渡されるいくつかのキー値を表し、ARGV は渡されるいくつかのパラメータを表します。 Lua コードは簡潔で読みにくいものにする必要があるため、これらのパラメータに対していくつかのコメントを記述することをお勧めします。

注: 上記のコードでは、複数の行にわたって `` が使用されています。 ` が配置されている行は空白のキャリッジ リターンも行とみなされますが、エラーを報告するときはコードの行番号を読み違えないようにしてください。

Lua スクリプトの実行

 updateRecordExpireScript.Run(c.Client, []string{recordKey(key)}, 
         expireField,
         time.Now().UTC().UnixNano(), int64(c.opt.RecordTTL/time.Second)).Err()
ログイン後にコピー

実行時、Run はまず EVALSHA を介してキャッシュを通じてスクリプトを実行しようとします。キャッシュがない場合は、EVAL を使用して実行すると、Lua スクリプト全体が Redis に渡されます。

Lua スクリプトの制限

  • Redis では、OS などの追加パッケージの導入は提供されません。利用できるのは Redis パッケージのみです。

  • Lua スクリプトは関数内で実行され、すべての変数はローカルを使用して宣言する必要があります。

  • return が複数の値を返す場合、Redis は最初の

スクリプト内の入力制限のみを示します

  • スクリプトが nil を返したときに Go で得られるものはい err = redis.Nil (Get が値を見つけられないのと同じ)

  • スクリプトが false を返した場合、Go で取得されるものは nil であり、スクリプトは true を返します。Go で取得されるのは int64 型です。1

  • スクリプトが {"ok": ...} を返すと、Go で取得されるのはステータス型です。 redis (true/false)

  • スクリプトが {"err": ...} を返すと、Go で err 値が取得されます。return redis を使用することもできます。 error_reply("My Error") Achieved

  • スクリプトが数値型を返すと、Go で取得されるのは int64 型です

  • スクリプトでは、必要に応じて、受信 KEYS/ ARGV の値を文字列タイプから数値タイプに変換するには、to_number 関数を使用する必要があります。

スクリプトの実行時間が長いですか?

Lua スクリプトの実行中は、他の操作によるデータの汚染を避けるため、この期間中は他のコマンドを実行できず、実行が完了するまで他のリクエストを続行できません。 Lua スクリプトの実行時間が lua-time-limit を超えると、他のリクエストは、SCRIPT KILL (スクリプトを強制終了) または SHUTDOWN NOSAVE (結果を保存せずに Redis を閉じる) でない限り、Busy エラーを受け取ります。

詳細ここでは主に私が Go を使用した経験に基づいていくつかの概要を説明します。 https://redis.io/commands/eval

より「複雑な」スクリプト。キー値を取得するときに、その値に頻繁にアクセスするとライフサイクルが延長される必要があります。また更新時間も比較する必要があり、更新が必要ない場合は取得した値をそのまま返しますが、そうでない場合はredis.Nil

// KEYS: rec:key, key
// ARGV: currentUnixTimestamp, hotHit, recordTTL, ttl
// When there's a hit,
var fetchRecordScript = redis.NewScript(local value = redis.call("GET", KEYS[2]) if(value == nil) then return nil end local hit = redis.call("HINCRBY", KEYS[1], "hit", 1) redis.call("EXPIRE", KEYS[1], ARGV[3]) local minHotHit = tonumber(ARGV[2]) local keyTTL = tonumber(ARGV[4]) if(hit > minHotHit)then keyTTL = keyTTL * 2 end redis.call("EXPIRE", KEYS[2], keyTTL) local expire = tonumber(redis.call("HGET", KEYS[1], "expire")) local unixTime = tonumber(ARGV[1]) if(expire == nil or expire < unixTime) then return nil else return value end)
// KEYS: key for record
// ARGV: fieldName, currentUnixTimestamp, recordTTL
// Update expire field of record key to current timestamp, and renew key expiration
var updateRecordExpireScript = redis.NewScript(redis.call("EXPIRE", KEYS[1], ARGV[3]) redis.call("HSET", KEYS[1], ARGV[1], ARGV[2]) return 1)
ログイン後にコピー
を返します。

以上がGo言語のLuaスクリプトでRedisを操作する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットな記事タグ

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Windows 11 10.0.22000.100 のインストール時の 0x80242008 エラーの解決策 Windows 11 10.0.22000.100 のインストール時の 0x80242008 エラーの解決策 May 08, 2024 pm 03:50 PM

Windows 11 10.0.22000.100 のインストール時の 0x80242008 エラーの解決策

golang でリフレクションを使用してプライベート フィールドとメソッドにアクセスする方法 golang でリフレクションを使用してプライベート フィールドとメソッドにアクセスする方法 May 03, 2024 pm 12:15 PM

golang でリフレクションを使用してプライベート フィールドとメソッドにアクセスする方法

Golang API のキャッシュ戦略と最適化 Golang API のキャッシュ戦略と最適化 May 07, 2024 pm 02:12 PM

Golang API のキャッシュ戦略と最適化

PHP 開発におけるキャッシュ メカニズムとアプリケーションの実践 PHP 開発におけるキャッシュ メカニズムとアプリケーションの実践 May 09, 2024 pm 01:30 PM

PHP 開発におけるキャッシュ メカニズムとアプリケーションの実践

Go 言語でのパフォーマンス テストと単体テストの違い Go 言語でのパフォーマンス テストと単体テストの違い May 08, 2024 pm 03:09 PM

Go 言語でのパフォーマンス テストと単体テストの違い

Win11 英語 21996 を簡体字中国語 22000 にアップグレードする方法_Win11 英語 21996 を簡体字中国語 22000 にアップグレードする方法 Win11 英語 21996 を簡体字中国語 22000 にアップグレードする方法_Win11 英語 21996 を簡体字中国語 22000 にアップグレードする方法 May 08, 2024 pm 05:10 PM

Win11 英語 21996 を簡体字中国語 22000 にアップグレードする方法_Win11 英語 21996 を簡体字中国語 22000 にアップグレードする方法

Golang テクノロジーを使用して分散システムを設計する場合、どのような落とし穴に注意する必要がありますか? Golang テクノロジーを使用して分散システムを設計する場合、どのような落とし穴に注意する必要がありますか? May 07, 2024 pm 12:39 PM

Golang テクノロジーを使用して分散システムを設計する場合、どのような落とし穴に注意する必要がありますか?

機械学習で使用される Golang テクノロジー ライブラリとツール 機械学習で使用される Golang テクノロジー ライブラリとツール May 08, 2024 pm 09:42 PM

機械学習で使用される Golang テクノロジー ライブラリとツール

See all articles