以下の内容はhttps://tech.guitarrapc.com/entry/2014/09/01/073504より取得しました。


C# や PowerShell から Redis を直接操作する RespClient というクライアント

私が所属する謎社では、CacheとしてRedisをフルに活用しています。Redis大好き最高です。 インタラクティブに操作するクライアントとしてredis-cliのお世話になります。

ビルトインで使えるとても有用なクライアントです。

しかしこのクライアントはLinux用で、Windowsで使えません。

Windowsから、かつC#、PowerShellからRedis Commandをインタラクティブに叩きたい。そんなあなたに今回は謎社で利用しているクライアントの紹介です。

RespClient

ResClient

弊社で使っているのは、 弊社のneueccが作ったRespClientです。

このクライアントの特徴は、Redis Protocol specificationつまり、RESPプロトコルを解釈してSocket経由で叩いていることです。

しかも、C# から呼ぶだけではなく、PowerShell Cmdletとしても実装されています。

MSOpenTech の Redisクローンはどうなのか

MSOpenTech大センセーのcloneならWindowsでもRedisが使えます。

しかし、C#、PowerShellから呼び出して制御したいのであって、外部コマンドをラップするのがどう考えてもいやです。そういう意味でも、RespClientのRESPを解釈してSocketで叩けるのはPowerShellから呼び出すにあたって正にあってほしい機能となります。

PowerShell から Cmdlet として使ってみよう

PowerShell Cmdletが実装されているということは、Moduleとしてdll提供されているということです。

PowerShellから呼び出す流れを見てみましょう。

GitHub

このクライアントはGitHubで公開されています。

まずはクローンなり、Zipをダウンロードするなりしてください。

ビルド

RespClient.slnを開いてさくっとビルドします。 VS2013であれば何も問題なくビルドできます。

image

Binary Module (.dll) の配置

生成された、RespClient\bin\Release\RespClient.dllをモジュールパスに配置するか、任意のパスにおきましょう。

image

$env:USERPROFILE\Documents\WindowsPowerShell\Modules\RespClient\RespClient.dllに配置すれば、PowerShell 3.0以降であれば、モジュールとして自動読み込まれるのでいい感じでしょう。

image

RespClient Module の読み込み

もし、モジュールパスに配置しなかった場合は、Import-Moduleを使って直接RespClient.dllを読み込んでください。

PowerShell ISEでも、PowerShell.exeでもいいのでお好きな方でどうぞ。

Import-Module RespClient.dll

モジュールパスに配置していた場合は不要です。

これで準備はできました。

RespClient で PowerShell から Redis を叩く

RespClient で公開されている Cmdlet

早速みてみましょう。

Get-Command -Module RespClient

これらのCmdletが公開されています。

CommandType Name                   ModuleName
----------- ----                   ----------
Cmdlet      Begin-RedisPipeline    RespClient
Cmdlet      Connect-RedisServer    RespClient
Cmdlet      Disconnect-RedisServer RespClient
Cmdlet      Execute-RedisPipeline  RespClient
Cmdlet      Get-RedisCurrentInfo   RespClient
Cmdlet      Send-RedisCommand      RespClient

早速使ってみましょう。

Redis ServerへのSocket接続を生成する

この時利用するのは、次のCmdletです。

Connect-RedisServer

ヘルプを見てみましょう。

help Connect-RedisServer -full
NAME
    Connect-RedisServer

SYNTAX
    Connect-RedisServer [[-Host] <string>] [[-Port] <int>] [[-IoTimeout] <int>]  [<CommonParameters>]


PARAMETERS
    -Host <string>

        Required?                    false
        Position?                    0
        Accept pipeline input?       false
        Parameter set name           (All)
        Aliases                      None
        Dynamic?                     false

    -IoTimeout <int>

        Required?                    false
        Position?                    2
        Accept pipeline input?       false
        Parameter set name           (All)
        Aliases                      None
        Dynamic?                     false

    -Port <int>

        Required?                    false
        Position?                    1
        Accept pipeline input?       false
        Parameter set name           (All)
        Aliases                      None
        Dynamic?                     false

    <CommonParameters>
        This cmdlet supports the common parameters: Verbose, Debug,
        ErrorAction, ErrorVariable, WarningAction, WarningVariable,
        OutBuffer, PipelineVariable, and OutVariable. For more information, see
        about_CommonParameters (https://go.microsoft.com/fwlink/?LinkID=113216).


INPUTS
    None


OUTPUTS
    System.Object

ALIASES
    None


REMARKS
    None

対象のRedisサーバーへのSocket接続を作ります。 Redisに親しんでいる方にはご存知の通り、HostアドレスとPortとIoTimeoutが設定可能です。 デフォルトでは127.0.0.1に6379で接続しますが、10.0.0.10のPort 7000で接続したい場合は次のようにします。

Connect-RedisServer -Host 10.0.0.10 -Port 7000

Socket接続は、一度接続すれば任意のタイミングできるまで接続しっぱなしなので、コマンド実行ごとに接続を作ったり渡す必要ありません。REPLには好ましい動作ですね。

現在のSocket接続を調べる

Socket接続で繋ぎっぱなしな以上、確認はしたくなりますね。

Cmdlet一発で取得できます。

Get-RedisCurrentInfo

結果です。

Host                                 Port                               IoTimeout
----                                 ----                               ---------
10.0.0.10                            6379                                      -1

Redis Serverへコマンドを送信する

Socket接続を作ったら早速コマンドを送信してみましょう。

これもCmdlet一発です。

Send-RedisCommand

ヘルプです。

NAME
    Send-RedisCommand

SYNTAX
    Send-RedisCommand [-Command] <string>  [<CommonParameters>]


PARAMETERS
    -Command <string>

        Required?                    true
        Position?                    0
        Accept pipeline input?       true (ByValue)
        Parameter set name           Command
        Aliases                      None
        Dynamic?                     false

    <CommonParameters>
        This cmdlet supports the common parameters: Verbose, Debug,
        ErrorAction, ErrorVariable, WarningAction, WarningVariable,
        OutBuffer, PipelineVariable, and OutVariable. For more information, see
        about_CommonParameters (https://go.microsoft.com/fwlink/?LinkID=113216).


INPUTS
    System.String


OUTPUTS
    System.Object

ALIASES
    None


REMARKS
    None

RedisのコマンドはさすがLinuxでStringです。なので、実行したいコマンドを文字列で渡して実行するだけです。簡単。

たとえば、 info cpuコマンドででCPU情報を取得してみるなら、こうです。

Send-RedisCommand -Command "info cpu"

結果がとれますね。

# CPU
used_cpu_sys:14346.90
used_cpu_user:1883.09
used_cpu_sys_children:90018.57
used_cpu_user_children:681373.81

もちろんPipeline入力にも対応しているのでこう書くこともできます。

"info cpu" | Send-RedisCommand

戻り値はUTF-8Stringで、デコードされています。PowerShell的にもUTF-8は望ましいのでいい感じでしょう。

パイプライン実行

Redisといえばパイプライン実行です。パイプラインによるアトミック性担保と高速処理えらい。 Cmdletでも対応していてくれて、最高です。

Begin-RedisPipeline
Send-RedisCommand "set test fghijk"
Send-RedisCommand "incr testb"
Send-RedisCommand "incr testc"
Send-RedisCommand "get test"
Execute-RedisPipeline

結果です。

OK
1
1
fghijk

パイプラインで実行されました。

流れを簡単に説明しましょう。まず、パイプラインの開始は、Begin-RedisPipelineで行います。

Begin-RedisPipeline

その間実行された、Send-RedisComamndは、すべて即時実行されずパイプラインにキューされます。

Send-RedisCommand "set test fghijk"
Send-RedisCommand "incr testb"
Send-RedisCommand "incr testc"
Send-RedisCommand "get test"

最後にExecute-RedisPipelienでパイプライン実行されます。

Execute-RedisPipeline

なかなかRedis-cliでパイプライン実行といわれてもすぐにピンと来なくてもPowerShell経由であれば直観的に操作できることが分かります。

Redis Serverとの Socket接続を切断する

Socket接続は、新しいConnect-RedisServerを行うことで前の接続は切断されます。

あるいは任意のタイミングで切断するには、Disconnect-RedisServerを使います。

Disconnect-RedisServer

接続されていない状態で、Send-RedisCommandを行ってもエラーがでるのでわかりやすいでしょう。

$ Send-RedisCommand "set test fghijk"

Send-RedisCommand : Server is not connecting
発生場所 行:1 文字:1
+ Send-RedisCommand "set test fghijk" | clip
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Send-RedisCommand], InvalidOperationException
    + FullyQualifiedErrorId : System.InvalidOperationException,Redis.PowerShell.Cmdlet.SendCommand

.NET呼び出し

もちろんPowerShell Cmdletではなく、.NET呼び出しも可能です。

ふつーにRespClientモジュールをインポートすれば準備は完了です。

Import-Module RespClient

サンプルC# コード

例えば、C# の次のコードをPowerShellで同様に書いてみましょう。

using (var client = new Redis.Protocol.RespClient())
{
    // string command
    client.SendCommand("set a 1", Encoding.UTF8.GetString);

    // binary safe command
    client.SendCommand("set", new[] { Encoding.UTF8.GetBytes("test"), Encoding.UTF8.GetBytes("abcde") }, Encoding.UTF8.GetString);

    // use pipeline
    var results = client.UsePipeline()
        .QueueCommand("incr a")
        .QueueCommand("incrby b 10")
        .QueueCommand("get a", Encoding.UTF8.GetString)
        .Execute();
} // disconnect on dispose

PowerShellにusingはないのでお察しですが。また、単純にはbinary safeな書き方ができないので、さっくりString Commandとuse pipelineで見てみましょう。*1

# connection
$client = New-Object Redis.Protocol.RespClient -ArgumentList &#40"10.0.0.10", 6379&#41

# string command
$client.SendCommand&#40"set a 1"&#41
$client.SendCommand&#40"get a"&#41

# use pipeline
$result = $client.UsePipeline&#40&#41.
    QueueCommand&#40"incr a"&#41.
    QueueCommand&#40"incrby b 10"&#41.
    QueueCommand&#40"get a"&#41.
    Execute&#40&#41;

# disconnect and dispose
$client.Dispose()
$client = $null

後置き記法ができなくてしょぼんですね。

まとめ

RespClientを使えばPowerShellからRedisが自在に操作できます。PowerShellに限らずさくっとC#からという用途でも是非ご活用ください。

*1:[System.Text.Encoding]::UTF-8.GetStringではすまないわけですよ。匿名コンストラクタでもほげ




以上の内容はhttps://tech.guitarrapc.com/entry/2014/09/01/073504より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14