この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
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クラスターに対してアクセスしている点に注意してください。