- Published on
Valkeyチュートリアル - Dockerでの構築からAmazon ElastiCacheまで
- Authors
- Name
- ryyta
- @fubar1346
tl:dr
携わっているプロダクトでキャッシュレイヤーを導入することになりました。 既存のインフラでAWSをメインに採用していることもあり、サービスとしてはAmazon ElastiCacheを利用することとしました。 RedisからForkしたValkeyも提供されていますが、2024年10月8日にServerless版もリリースされ、さらにRedisよりも安価に利用できること、Serverless版ではクラスターモードの利用になることから ローカル検証用にDockerでもValkey Clusterを構築し、またプロダクション用途でValkey for Serverlessを利用するところまでを整理します。
Valkey CLI
Macの場合、 brew install valkey
でインストールできます。
Docker上でのValkey(No Cluster)構築
ValkeyのDockerイメージは公式で提供されているため、Docker Composeを使って簡単に構築できます。
以下のdocker-compose.yml
をそのまま利用することで簡単にValkeyのコンテナを起動できます。
version: "3.9"
services:
valkey_container_1:
image: valkey/valkey:8.0.1
container_name: valkey_container_1
ports:
- "6379:6379"
volumes:
- valkey-data:/var/lib/valkey
volumes:
valkey-data:
docker exec -it valkey_container_1 valkey-cli
でValkeyのCLIに接続できます。
もしくはホストマシンからでも接続可能です。
$ valkey-cli -h localhost -p 6379
接続後、簡単な動作確認を行います。
127.0.0.1:6379> set test_key test_value
ok
127.0.0.1:6379> get test_key
"test_value"
Docker上でのValkey Cluster構築
Docker上でクラスターモードを構築する場合、以下のようなdocker-compose.yml
を利用します。 3つのノードを構築し、それぞれのノードには違うポートを割り当てます。 その上で1つのClusterとしてまとめるようにします。
version: "3.9"
services:
valkey-nodes-1:
image: valkey/valkey:8.0.1
container_name: valkey-nodes-1
ports:
- "6379:6379"
volumes:
- valkey-nodes-data1:/var/lib/valkey
networks:
valkey-cluster:
ipv4_address: 192.168.4.101
command: >
sh -c "
valkey-server --port 6379 --cluster-enabled yes
--cluster-config-file nodes.conf
--cluster-node-timeout 5000
--appendonly yes
--protected-mode no
--dir /var/lib/valkey &&
tail -f /dev/null
"
valkey-nodes-2:
image: valkey/valkey:8.0.1
container_name: valkey-nodes-2
ports:
- "6380:6379"
volumes:
- valkey-nodes-data2:/var/lib/valkey
networks:
valkey-cluster:
ipv4_address: 192.168.4.102
command: >
sh -c "
valkey-server --port 6379 --cluster-enabled yes
--cluster-config-file nodes.conf
--cluster-node-timeout 5000
--appendonly yes
--protected-mode no
--dir /var/lib/valkey &&
tail -f /dev/null
"
valkey-nodes-3:
image: valkey/valkey:8.0.1
container_name: valkey-nodes-3
ports:
- "6381:6379"
volumes:
- valkey-nodes-data3:/var/lib/valkey
networks:
valkey-cluster:
ipv4_address: 192.168.4.103
command: >
sh -c "
valkey-server --port 6379 --cluster-enabled yes
--cluster-config-file nodes.conf
--cluster-node-timeout 5000
--appendonly yes
--protected-mode no
--dir /var/lib/valkey &&
tail -f /dev/null
"
valkey-cluster:
image: valkey/valkey:8.0.1
container_name: valkey-cluster
depends_on:
- valkey-nodes-1
- valkey-nodes-2
- valkey-nodes-3
networks:
- valkey-cluster
entrypoint: >
sh -c "
sleep 10 &&
echo 'yes' | valkey-cli --cluster create \
192.168.4.101:6379 192.168.4.102:6379 192.168.4.103:6379 \
--cluster-replicas 0 &&
tail -f /dev/null
"
volumes:
valkey-nodes-data1:
valkey-nodes-data2:
valkey-nodes-data3:
networks:
valkey-cluster:
driver: bridge
ipam:
config:
- subnet: 192.168.4.0/24
3つのValkeyノードを構築し、それをまとめる形で valkey-cluster
を構築しています。
以下のコマンドで構築したClusterの状態を確認できます。
$ valkey-cli -h localhost -p 6379 cluster nodes
// 以下のような出力が得られる
192.168.4.103:6379@16379 master - 0 1733572817000 3 connected 10923-16383
192.168.4.101:6379@16379 myself,master - 0 0 1 connected 0-5460
192.168.4.102:6379@16379 master - 0 1733572818461 2 connected 5461-10922
connected
の後ろの部分の数字のレンジは、各ノードが担当するスロットの範囲を示しています。
クラスターモードではキーがハッシュスロットに基づいて分散されるので、入力値のキーは計算結果に基づいてノードに振り分けられます。
Valkey(Redis)ではキーが 0 - 16383
の範囲でハッシュされます。
入力キーに対してCRC16ハッシュを計算し、その結果を16384で割った余りがスロット番号となります。
- Redis cluster specification:Key distribution model
- Documentation: Valkey cluster specification:Key distribution model
クラスターモードのValkeyで値の追加と取得を行ってみます。
CLIで操作する場合は、特定のノードを指定して操作する必要があります。今回は valkey-nodes-1
に接続して操作します。
-c
オプションをつけることでクラスターモードでの操作が可能になります。
$ docker exec -it valkey-nodes-1 valkey-cli -c -p 6379
以下、クラスターモードで接続したCLIでの操作例です。
$ docker exec -it valkey-nodes-1 valkey-cli -c -p 6379
127.0.0.1:6379> set test-data-1 "cluster mode test"
OK
127.0.0.1:6379> get test-data-1
"cluster mode test"
127.0.0.1:6379> set test-data-2 "cluster mode test-2"
-> Redirected to slot [14064] located at 192.168.4.103:6379
OK
127.0.0.1:6379> get test-data-2
-> Redirected to slot [14064] located at 192.168.4.103:6379
"cluster mode test-2"
1回目のデータの追加では test-data-1
をキーにしていますが、これはハッシュスロットがvalkey-nodes-1
に割り当てられているためそのまま追加できます。
2回目のデータの追加ではtest-data-2
をキーにしていますが、これはハッシュスロットがvalkey-nodes-3
に割り当てられているため、valkey-nodes-3
(192.168.4.103:6379)にリダイレクトされて追加されます。
同様に、test-data-2
の取得もリダイレクトされてvalkey-nodes-3
から取得されます。
Node.jsでのValkeyの利用
Node.jsでValkeyを利用する場合、 ライブラリを用いて操作します。 今回はRedis
用に作られたioredis
というライブラリからValkey
用にForkされたiovalkey
を利用します。
TypeORMなどのライブラリに組み込んで使用する場合、現時点でiovalkey
はサポートされていないため、直接iovalkey
を利用するか、ioredis
を使用することになります。
この記事を書いている時点では双方に大きな差はないので、ioredis
の使用でも問題ないかと思います。
一番シンプルに、これまで構築したDockerコンテナを使ってローカル環境で動かすのは以下のようになります。
import { Cluster } from 'iovalkey';
const cluster = new Cluster([
{host: 'valkey-nodes-1', port: 6379},
{host: 'valkey-nodes-2', port: 6379},
{host: 'valkey-nodes-3', port: 6379}
])
実際にはオプションやパスワードの設定等の実装を行う場合がほとんどだと思います。
import { Cluster } from 'iovalkey';
const cluster = new Cluster([
{host: 'valkey-nodes-1', port: 6379},
{host: 'valkey-nodes-2', port: 6379},
{host: 'valkey-nodes-3', port: 6379}
],{
// @see: https://github.com/luin/ioredis#special-note-aws-elasticache-clusters-with-tls
dnsLookup: (address, callback) => callback(null, address), // Amazon ElastiCacheの場合に必要
clusterRetryStrategy(times) {
if (times > 5) {
console.error('Too many retries, giving up on connection.')
return null
}
console.log(`Retrying cluster connection, attempt ${times}`)
return 2000 // 2秒後に再試行
},
redisOptions: {
username: 'username' // ElastiCacheでアクセスコントロール設定済みの場合、アプリケーション用に設定したユーザ名を指定
password: 'password', // 上記ユーザ名に対応するパスワードを設定
connectTimeout: 10000,
tls: {} // TLS有効の場合に必要。Amazon ElastiCache for Valkey Serverlessの場合は必須
}
})
Amazon ElastiCache for Valkey Serverlessの場合、TLSが必ず有効になっているため、tls: {}
を設定する必要があります。 またdnsLookup
もAmazon ElastiCacheの場合に必要になります。
- iovalkey:Special Note: Aws Elasticache Clusters with TLS
- ioredis:Special Note: Aws Elasticache Clusters with TLS
Valkey(Redis)で使用できるGUIツール
CLIを使えばValkey内に保持したデータの確認などは可能ですが、毎度CLIを使うのは面倒なのでGUIツールを使うようにします。
個人的には以下のどちらかを使います。
Medis2
MacのApp Storeからもダウンロード可能で手軽に使用できます。
クラスターモードにも対応していますし、UIもシンプルで使いやすいのでローカルでの開発でも使いやすいGUIです。
RedisInsight
RedisInsightはRedisの公式で提供されているGUIツールです。
プロダクション環境での利用も可能で、クラスターモードにも対応しています。
Redis CopilotというAI機能も搭載されており、データ分析等にも使えるようになっています。
EC2上に構築し、オンライでは運用しているRedis(Valkey)に接続して利用することも可能で、オフラインではS3等に保存しているデータを使った分析などが可能です。
RedisInsightの場合には、ローカル環境での使用の場合には提供されているDockerイメージを使って立ち上げます。
# これまでのdocker-compose.ymlに追記
redisinsight:
image: redislabs/redisinsight:latest
container_name: redisinsight
ports:
- 5540:5540
volumes:
- redisinsight-data:/db
networks:
- valkey-cluster
depends_on:
- valkey-cluster
volumes:
valkey-nodes-data1:
valkey-nodes-data2:
valkey-nodes-data3:
redisinsight-data: ## 追加
上記を追加して再度 docker compose up
でRedisInsightが立ち上がるので、localhost:5540
にアクセスすることでRedisInsightのGUIが表示されます。
ローカル環境の場合は、[+ Add Redis Connection]から接続先を追加します。
今回はhostにノードを指定することで接続できます
すべてのデータを確認できますし、Workbenchからはコマンドを使った操作も可能です。
またPub/Sub用の機能も提供されているので、Pub/Subの確認も可能です。
さらにAnalytics機能ではクラスター内のすべてのノードのデータを分析することも可能で、非常に便利なツールです。
プロダクション環境で利用すれば各ノードの状況把握も容易になりますし、開発時点でも例えばテストデータを用いたデータ分散の確認なども行えるので、キャッシュ設計等でも非常に使えそうです。
Amazon ElastiCache for Valkey Serverless の構築と接続
構築の詳細は公式でも提供されているので省略しますが、プロダクトでの連携で注意すべきポイントだけ記載します。
- Amazon ElastiCache for Valkey Serverlessはクラスターモードのみの提供 これまではValkeyはServerless版の提供がなく、その時点まではクラスターモードを有効にするかどうかは自由に選択できました。
しかしServlerssではクラスターモードのみの提供となるため、クラスターモードでの運用を前提として設計する必要があります。
上記であげた iovalkey
を使用する場合でも、new Valkey.Cluster
でクラスターモードを有効にする必要があります。
- Serlerss版ではTLSが有効になっている こちらもServerless版から必須になった設定ですが、TLSが有効になっているため、
tls: {}
の設定が必要になります。
CLIでも --tls
オプションをつける必要があるため、これまでよりもセキュリティが強化されている反面、接続の際には注意が必要です。
- クラスターモードでは
dnsLookup: (address, callback) => callback(null, address)
の設定が必要 Amazon ElastiCacheをClusterで利用する場合、証明書関係のエラーになり接続がうまくいかないケースがあります。
その回避のため、以下のように設定を行います。
import { Cluster } from 'iovalkey';
const cluster = new Cluster([
{
host: 'hostname',
port: "port"
}
], {
dnsLookup: (address, callback) => callback(null, address), // Amazon ElastiCacheの場合に必要
redisOptions: {
password: 'password', // パスワードが設定されている場合
connectTimeout: 10000,
tls: {} // TLS有効の場合に必要。Amazon ElastiCache for Valkey Serverlessの場合は必須
}
})
Amazon ElastiCache for Valkey Serverlessへの監視
EC2に上記で紹介したRedisInsightを構築するなどしてメモリ分析やキーの分散、保持しているデータの確認などが可能です。
方法については今後追記しますが、以下の記事などが参考になるかと思います。
Redisをグラフィカルに確認できるRedisInsightでElastiCache Redisのメモリ分析してみた