[Rust]Amazon MemoryDB for Redis にプログラムからアクセスする[JavaScript]

2022.02.15

Introduction

Amazon MemoryDB for Redis(以下 MemoryDB)とは、
高可用性かつ耐久性に優れたインメモリデータベースです。
Redis互換なのでioredisやredis-rsなど、
通常のredisクライアントを使用して接続できます。
本稿ではRust/JavaScriptからMemoryDBにアクセスする方法についてご紹介します。

Amazon MemoryDB for Redis?

MemoryDBは、最近東京リージョンでも使用できるようになった、
高速なインメモリデータベースです。
いままでredisといえばキャッシュ用途やWebアプリのセッションデータ保存用途などで
よく選択肢にあがってきてましたが、
これは永続的なデータストとして使えます。

MemoryDBについてはここに詳細な記事があるので、参照してください。

Environment

動作環境です。
aws cliは実行可能な前提です。

  • MacBook Pro (13-inch, M1, 2020)
  • OS : MacOS 11.3.1
  • Rust : 1.58.1

MemoryDBをセットアップ

まずは今回使用するMemoryDBを作成します。
ここでクラスターの作成をして、
Configuration endpointを確認しておきましょう。

その後、動作確認のため同じVPC内にEC2インスタンスを作成して、SSHでログインします。
※ MememoryDBのセキュリティグループ設定でEC2のセキュリティグループのアクセスを許可  

動作確認用に、redisをインストールしましょう。

% sudo yum -y install openssl-devel gcc
% wget http://download.redis.io/redis-stable.tar.gz
% tar xvzf redis-stable.tar.gz
% cd redis-stable
% make distclean
% make redis-cli BUILD_TLS=yes
% sudo install -m 755 src/redis-cli /usr/local/bin/

redis-cliでMemoryDBに接続します。

% redis-cli -h <Configuration endpoint> --tls -p <Port番号> -c

setとgetをそれぞれ試してみます。

your-memorydb:6379>; set memorydb-key "hello memory-db"
OK
your-memorydb:6379>; get memorydb-key
"hello memory-db"

問題なく操作できてます。
では次に、ここでsetした値をプログラムから取得してみましょう。

[参考]

Create Example(Node)

では↑のEC2にNodeをインストールしてアクセスしてみます。
※ Nodeのインストールはこのへん参照

% curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash
% . ~/.nvm/nvm.sh
% nvm install node
% node -v
v17.5.0

NodeからMemoryDBへのアクセスはioredisを使います。

% mkdir node-memorydb && cd node-memorydb
% npm install --save ioredis

JavaScriptのコードを記述。
↑で設定した値をMemoryDBから取得してみます。

//main.js
const Redis = require("ioredis");
//TLSなのでrediss://〜
const HOST = "rediss://<Configuration endpoint>:<Port番号>/";
const redis = new Redis(HOST);

async function get_value() {
        var memorydb_value = await redis.get('memorydb-key');
        return memorydb_value;
}

async function main() {
    const value =  await get_value();
    console.log(value);
    process.exit(0);
}

main();

注意点は、MemoryDBは暗号化されているので接続するにはURLがrediss://〜になるところです。  

ローカルにインストールしたRedisは↑で動いたから、
そのままいけるかと思いましたが、エラー。

MOVED 2247 :<Configuration endpoint>:<Port番号>"

コマンドに対応するハッシュスロットが別ノードにある場合のエラーみたいです。
なので、通常のRedisクライアントではなく、
クラスターに対して接続する必要があります。

//main.js
const Redis = require("ioredis");

//Redisクラスターに対して接続
const redis = new Redis.Cluster(
            [{ "host": "<Configuration endpoint>" }], {
                dnsLookup: (address, callback) => callback(null, address),
                redisOptions: {
                    tls: true,
                }
            });

async function get_value() {
        var memorydb_value = await redis.get('memorydb-key');
        return memorydb_value;
}


async function main() {
    const value =  await get_value();
    console.log(value);
    process.exit(0);
}

main();

hostの指定方法が少し違うので注意。(rediss://〜ではない)

% node main.js
hello memory-db

動作OKです。

Create Example(Rust)

Rustでも試してみましょう。
このあたりを参考にRustをインストールしたら、
Cargoでプロジェクトを作成します。

% cargo new sample-memorydb && cd sample-memorydb

RustでのMemoryDB接続はredis-rsを使うので、
Cargo.tomlに↓の記述を追加します。

[dependencies]
redis = { version = "0.21.5", features = ["tls","cluster"] }

main.rsを下記のようにします。
Rustでも通常のClientを使用すると、動いたり動かなかったりするので注意。
ClusterClientを使います。

//main.rs
use redis::cluster::ClusterClient;
use redis::Commands;

fn get_value(key:&str) -> redis::RedisResult {
    let nodes = vec!["rediss://<Configuration endpoint>:<Port番号>"];
    let client = ClusterClient::open(nodes).unwrap();
    let mut con = client.get_connection()?;
    con.get(key)
}

fn main() {
    let key = "memorydb-key";
    match get_value(key) {
        Ok(v) => println!("{:?}", v),
        Err(err) => println!("Error:{}", err),
    }
}

runで実行してみます。

% cargo run
"hello memory-db"

こちらも動作確認OKです。

Summary

今回はMemoryDBに対してJavaScript、Rustからそれぞれアクセスしてみました。
単一のRedisでなく、Redisクラスターに対してアクセスしている点に注意してください。