ElastiCacheの複数のRedisインスタンスのデータを移植し、1つに統合する。

Redisはキャッシュサーバーでありながら、データの冗長化や永続化さらにはソートされたデータの順位の計算も可能なため、(本当は良くないと分かりながらも)つい保存しなければならないデータまでRedisに格納する運用をしていた。

しかし、コスト削減のため1つのサーバーにデータを統合する想定があまりないのか、かなり面倒くさい…しなかなか情報もないという問題があった。

https://www.slideshare.net/ssuserf3788f/redis-58419914 こちらの資料が非常に参考になったが、AWS ElastiCacheのアップデートによって変わった点や他に調べないとわからない点があったため、より具体的に手順を記述する。

手順1:Redisのスナップショットを取得する。

// aws_region,cache-cluster-idは自分の環境に合わせてください。
// S3 bucketを用意してない場合は予め作成してください
aws_region=ap-northeast-1
cache_cluster_id=redis-a
snapshot_name=redis-snapshot-a
s3_bucket_name=bucket-a

aws elasticache create-snapshot \
    --snapshot-name $snapshot_name \
    --cache-cluster-id $cache_cluster_id \
    --region $aws_region

手順2:保存するS3バケットにスナップショット作成用権限を一時的に付与する

理由についてはこちらのドキュメントが参考になります。

aws s3api put-bucket-acl --bucket $s3_bucket_name --grant-full-control id=540804c33a284a299d2547575ce1010f2312ef3da9b3a053c8bc45bf233e4353

手順3:作成したRedisのスナップショットをS3にコピーする。

aws elasticache copy-snapshot \
    --source-snapshot-name $snapshot_name \
    --target-snapshot-name $snapshot_name \
    --target-bucket $s3_bucket_name \
    --region $aws_region

手順4:S3からスナップショットファイルをダウンロードする。

手順5:ダウンロードしたスナップショットをマージする。

以下のコードを実行して、生成されたファイルをS3にアップロードする。RedisのDumpファイルの中身の構造についてはこちらが参考になった。

またチェックサムの計算の方法については調べても中々出てこずに手間取ったが、こちらの実装コメントが参考になった。

※こちらのスクリプトは1つのRedisスナップショットに複数DBが含まれているケースは想定していない。順に、DB0に1つ目のスナップショットのDB、DB1に2つ目のスナップショット…という具合に結合している。

merge_redis_dump.rb

require 'crc'

file_names = [
  'redis-snapshot-a.rdb',
  'redis-snapshot-b.rdb',
  'redis-snapshot-c.rdb',
]

merged_file = file_names.each_with_index.inject("") do |merged_file_str, (file_name, index)|
  file_str = File.binread(file_name)
  if index != 0
    file_str.slice!(0..10)
    file_str.insert(0, [254, index].pack("C*"))
  end

  if index == file_names.size - 1
    file_str.slice!(file_str.size - 8..file_str.size - 1)
  else
    file_str.slice!(file_str.size - 9..file_str.size - 1)
  end
  merged_file_str << file_str
end

crc = CRC.new(64, 0xad93d23594c935a9, initial_crc = 0, refin = true, refout = true, xor_output = 0)
checksum = crc.digest(merged_file).unpack("C*").reverse.pack("C*")

merged_file << checksum

IO.binwrite("redis-snapshot-merged.rdb", merged_file)

作成したファイルのチェック

redis-check-dump redis-snapshot-merged.rdb
  • 手順6:S3にアップロードする。
  • 手順7:アップロードしたファイルに、スナップショット利用権限を付与する。
aws s3api put-object-acl --bucket $s3_bucket_name --grant-full-control id=540804c33a284a299d2547575ce1010f2312ef3da9b3a053c8bc45bf233e4353 --key redis-snapshot-merged.rdb

手順8:新しいRedisサーバーをスナップショットから立ち上げる

ドキュメントはこちら

一例:

aws elasticache create-cache-cluster \
--cache-cluster-id my-cluster \
--cache-node-type cache.r5.large \
--engine redis \
--engine-version 3.2.4 \
--num-cache-nodes 1 \
--cache-parameter-group default.redis3.2 \
--snapshot-arns arn:aws:s3:$(echo $s3_bucket_name)/redis-snapshot-merged.rdb

コメントを残す

メールアドレスが公開されることはありません。