ElastiCache for RedisからValkeyへの移行
はじめに
2024年3月、Redisはライセンスを**SSPL(Server Side Public License)**へ変更しました。
これに伴って、ElastiCache for RedisからValkeyへの移行を実施しました。
Valkey選定の理由
理由はいくつかありますが、特に大きな決め手となったのは 完全な後方互換性 と コスト削減 の 2 点 です。
1. 完全な後方互換性
Redis クライアントライブラリをそのまま使用可能であり、既存のコードを修正する必要が無いからです。
2. コスト削減
Redis と比べて Valkey は費用が安くなるからです。
ElastiCache Serverless for Valkey は Redis OSSよりも33%安く、ノードベースの ElastiCache for Valkey は 他のノードベースの ElastiCache エンジンよりも 20%安くなるからです。
参考:Amazon ElastiCache and Amazon MemoryDB announce support for Valkey
弊プロダクトでは ElastiCache Serverless for Valkey ではなく、ノードベースの ElastiCache for Valkey を選定しました。
ElastiCache for Valkey を選んだ理由
現在、バックグラウンドジョブの処理に Sidekiq OSSを使用しており、クラスタモード(クラスタ構成)に対応していません。そのため、クラスタモードが必須の ElastiCache Serverless for Valkey は利用できず、既存の単一ノード構成(クラスタモード無効)で移行可能な ElastiCache for Valkey を選択しました。
※ ただし、将来的にSidekiq Proへのアップグレードを検討する場合は、クラスタ構成が利用できるようになるため、そのタイミングでElastiCache Serverless for Valkey への移行も選択肢に入ります。
移行手順
local
下記修正のみで移行は完了しました。
redis:
- image: redis:6.2.6-alpine # https://hub.docker.com/_/redis
+ image: valkey/valkey:8.0.1-alpine # https://hub.docker.com/r/valkey/valkey
volumes:
- - ./tmp/redis:/data:delegated
+ - valkey:/data
- command: redis-server
+ command: valkey-server
ports:
- 16379:6379
volumes:
db:
+ valkey:
production
1.tfファイル修正
- resource "aws_elasticache_cluster" "sample" {
- cluster_id = "sample-${var.stage}"
- engine = "redis"
- engine_version = "6.2"
- node_type = "cache.t2.micro"
- num_cache_nodes = 1
- parameter_group_name = aws_elasticache_parameter_group.sample.name
- port = 6379
- subnet_group_name = aws_elasticache_subnet_group.sample.name
- security_group_ids = [aws_security_group.redis.id]
+ resource "aws_elasticache_replication_group" "cache" {
+ replication_group_id = "sample-${var.stage}"
+ description = "sample-${var.stage} Valkey cluster"
+ engine = "valkey"
+ engine_version = "8.0"
+ node_type = "cache.t2.micro"
+ num_cache_clusters = 1
+ parameter_group_name = aws_elasticache_parameter_group.sample.name
+ port = 6379
+ subnet_group_name = aws_elasticache_subnet_group.sample.name
+ security_group_ids = [aws_security_group.redis.id]
+ automatic_failover_enabled = false
+ multi_az_enabled = false
+ }
resource "aws_elasticache_parameter_group" "sample" {
name = "sample-${var.stage}"
- family = "redis6.x"
+ family = "valkey8"
parameter {
name = "databases"
value = "64"
}
}
resource "aws_route53_record" "redis" {
zone_id = aws_route53_zone.sample-tokyo-private.zone_id
name = "redis.${var.stage}.sample.tokyo"
type = "CNAME"
ttl = "300"
- records = [aws_elasticache_cluster.sample.cache_nodes[0].address]
+ records = [aws_elasticache_replication_group.sample.primary_endpoint_address]
}
主な変更点
| 項目 | 変更前 | 変更後 | 理由 |
|---|---|---|---|
| リソースタイプ | aws_elasticache_cluster |
aws_elasticache_replication_group |
ValkeyはReplicationGroup APIが必須 |
| ID属性名 | cluster_id |
replication_group_id |
リソースタイプ変更に伴う |
| エンジン | redis |
valkey |
Valkeyへの移行 |
| バージョン | 6.2 |
8.0 |
Valkey 8.0へアップグレード |
| ノード数属性 | num_cache_nodes |
num_cache_clusters |
リソースタイプ変更に伴う |
| 新規追加 | - | description |
ReplicationGroupで必須 |
| 新規追加 | - | automatic_failover_enabled = false |
単一ノードの場合false |
| 新規追加 | - | multi_az_enabled = false |
単一ノードの場合false |
| Route53レコード参照 | cache_nodes[0].address |
primary_endpoint_address |
リソース変更に伴うエンドポイント参照方法の変更 |
2.環境変数(REDIS_URL)更新
## SSMの現状確認
$ aws ssm get-parameter --name "/sample-production/REDIS_URL" --region ap-
northeast-1 --with-decryption --query 'Parameter.Value' --output text
## 更新
$ aws ssm put-parameter --name "/sample-production/REDIS_URL" --value
"redis://redis.production.sample.tokyo:6379" --type "String" --overwrite --
region ap-northeast-1
3.環境変数反映の為 ECS サービスを再デプロイ
移行で発生した問題とその解決策
1.CreateCacheCluster API が Valkey に非対応
発生した問題
Error: creating ElastiCache Cache Cluster (app-sample-production):
operation error ElastiCache: CreateCacheCluster
https response error StatusCode: 400
InvalidParameterValue: This API doesn't support Valkey engine.
Please use CreateReplicationGroup API for Valkey cluster creation.
ValkeyはCreateCacheCluster APIではなく、CreateReplicationGroup APIで作成する必要がありました。
解決策
Terraformリソースをaws_elasticache_clusterからaws_elasticache_replication_groupに変更しました。
2.DNS名の不一致による接続エラー
発生した問題
RedisClient::CannotConnectError Events (total) Users (90d) Level: Error
getaddrinfo: Name does not resolve
(redis://sample-production.vg1jxe.0001.apne1.cache.amazonaws.com:6379)
(RedisClient::CannotConnectError)
環境変数 REDIS_URL の値が、旧Redisクラスタのエンドポイント(sample-production.vg1jxe.0001.apne1.cache.amazonaws.com)のままでした。新Valkeyクラスタ作成後、このエンドポイントは存在しなくなり、アプリケーションが古いURLに接続しようとしていました。
解決策
SSM Parameter Store で REDIS_URL を新Valkeyクラスタのエンドポイントに更新後、環境変数の変更を反映させるため ECS サービスを再デプロイしました。
Discussion