ENECHANGE Developer Blog

ENECHANGE開発者ブログ

ElastiCache for RedisをValkeyへ移行しました

エネルギークラウド事業部でバックエンドエンジニアをしている白坂です。

2024年10月から Amazon ElastiCache for Valkey が利用できるようになったため、私たちのチームでも Redis から Valkey への移行を行いました。
この記事ではその際につまずいたポイントをまとめます。

移行の背景

Valkeyに移行した最大の理由は、インフラコスト削減です。

  • ElastiCache Serverless を使えば 33%のコスト削減

  • オンデマンドノードでも 20%のコスト削減

aws.amazon.com

加えて、以下のような理由も後押しとなりました。

  • パフォーマンスの向上

  • Redis OSSのAPI互換性があるため、コード変更は最小限

  • ダウンタイムゼロでの移行も可能(ただし後述の通り条件あり)

つまずいたポイント

1. TerraformのAWSプロバイダのバージョン

Terraform設定では以下のように AWSプロバイダv4.X にしていました。

required_providers {
  aws = {
    source  = "hashicorp/aws"
    version = "~> 4.0"
  }
}

しかし、Valkeyに対応しているのはv5.73.0以降 です。
そのため、現状のコードだと下記のエラーが出ました。

Error: expected engine to be one of [redis], got valkey

github.com

2. シングルノード構成だとValkeyへの移行ができない

私たちのプロダクトは、ElastiCache for Redisを使用し、オンデマンドノードによるシングルノード構成で運用していました。
レプリケーショングループは作成しておらず、Terraformの設定は以下のようになっていました。

resource "aws_elasticache_cluster" "this" {
  cluster_id                = "${var.resource_name_prefix}-cache"
  engine                    = "redis"
  node_type                 = var.cache_node_type
  num_cache_nodes           = 1
  parameter_group_name      = "default.redis6.x"
  engine_version            = "6.2"
  port                      = 6379
  final_snapshot_identifier = "${var.resource_name_prefix}-cache-final-snapshot"
  maintenance_window        = "sat:17:00-sat:20:00" 
  snapshot_window           = "15:00-17:00"
  security_group_ids        = [aws_security_group.cache.id]
  subnet_group_name         = aws_elasticache_subnet_group.this.name
}

この状態で、 redisvalkey に書き換えてterraform applyを実行したところ、以下のエラーが発生しました。

Error: creating ElastiCache Cache Cluster (test-cache-name): operation error ElastiCache: CreateCacheCluster, https response error StatusCode: 400, RequestID: e7e1cc26-d236-4e2e-9b8f-5e4ed5fad9d3, InvalidParameterValue: This API doesn't support Valkey engine. Please use CreateReplicationGroup API for Valkey cluster creation.

同様のエラーはマネジメントコンソールからエンジンを変更しようとした場合にも発生しました。

aws_elasticache_cluster リソースでは Valkey への移行をサポートしていないため、シングルノード構成をやめてレプリケーショングループを作成することにしました。

resource "aws_elasticache_replication_group" "this" {
  replication_group_id       = "${var.resource_name_prefix}-rep-group"
  description                = "ElastiCache for Valkey"
  engine                     = "valkey"
  engine_version             = "8.0"
  automatic_failover_enabled = false
  node_type                  = var.cache_node_type
  parameter_group_name       = "default.valkey8"
  port                       = 6379
  apply_immediately          = false
  maintenance_window         = "sat:17:00-sat:20:00"
  snapshot_window            = "15:00-17:00" 
  notification_topic_arn     = "arn:aws:sns:ap-northeast-1:899381291843:${var.dev_monitoring_topic_name}"
  subnet_group_name          = aws_elasticache_subnet_group.this.name
  security_group_ids         = [aws_security_group.cache.id]
}

ElastiCacheはノード数毎に課金されるため、レプリケーショングループを作成してもクラスターモードを disabled にしてノード数を1つにすれば、シングルノード構成と料金は変わりません。

私たちのプロダクトでは、運用中にElastiCacheのデータが消失することダウンタイムの発生が許容されるため、既存のRedisノードを削除し、新たにValkey用のレプリケーショングループを構築する方針にしました。
今回、ElastiCacheの構成によってはダウンタイムゼロでの移行はできないこともあるということが分かりました。

3. アプリケーションコードの変更は必要なかった

私たちのプロダクトはPython + Django + Celery 構成で、Redisを以下の用途で使用していました。

  • Celeryのブローカー
  • Celeryのバックエンド
  • Djangoのキャッシュバックエンド

結果としてコードの修正は不要でした。

  • Redis URLredis://)をそのまま使うことができる
  • django-redisredis-pyCeleryもそのままで動作する

ですが、将来的にValkeyが独自機能を追加していく可能性があるため、django-valkeyvalkey-pyへの移行も検討しておいた方が良さそうです。
また、プロダクトの要件によっては valkey-glide というライブラリも使えそうです。

その他

また、今回 Redis6.2 から Valkey8.0.1 にアップデートしているため、下記のリリースノートを確認しました。
私たちのプロダクトに影響する破壊的な変更点はありませんでした。

github.com

github.com

docs.aws.amazon.com

まとめ

Valkey8.0 でさらなるパフォーマンス向上がされているようなので、RedisからValkeyへの移行はメリットが大きいと感じています。
Redis7.4以降はValkeyとの互換性がなくなってしまうため、Redisから早めに移行しておいた方が良さそうです。