ElastiCache Valkey 跨账号跨 Region 停机迁移 Hands-On
验证:未记录
- 适用版本
- 未记录
- 验证范围
- 尚未登记验证记录。
本文缩写(英文全称与中文含义)
| 缩写 | 英文全称/名称 | 中文含义 |
|---|---|---|
| ACL | Access Control List | 访问控制列表 |
| ARN | Amazon Resource Name | AWS 资源名称,用于唯一标识资源 |
| KMS | Key Management Service | 密钥管理服务 |
| RDB | Redis Database snapshot | Redis 数据库快照格式 |
| S3 | Simple Storage Service | AWS 对象存储服务 |
| TLS | Transport Layer Security | 传输层安全协议 |
| TTL | Time To Live | 存活时间;具体指缓存有效期或记录过期时间 |
| URL | Uniform Resource Locator | 统一资源定位符,通常指访问地址 |
1. Flow#
本文针对 node-based ElastiCache for Valkey replication group:
stop Account A writers
-> create final snapshot
-> export RDB to Account A S3
-> copy RDB to Account B / target Region S3
-> create B2 from RDB
-> validate
-> switch applicationElastiCache Serverless 不使用本文的 create-replication-group 命令。
2. Variables#
SOURCE_PROFILE=account-a
SOURCE_REGION=ap-east-1
SOURCE_REPLICATION_GROUP=A1
SOURCE_BUCKET=ACCOUNT-A-SOURCE-REGION-BUCKET
DESTINATION_PROFILE=account-b
DESTINATION_REGION=ap-southeast-1
DESTINATION_REPLICATION_GROUP=B2
DESTINATION_BUCKET=ACCOUNT-B-DESTINATION-REGION-BUCKET
MIGRATION_ID="$(date -u +%Y%m%dT%H%M%SZ)"
SNAPSHOT_NAME="a1-migration-${MIGRATION_ID}"
EXPORT_NAME="a1-export-${MIGRATION_ID}"Before the outage, prepare in Account B:
ElastiCache subnet group
security group
Valkey parameter group
KMS key
user group/ACL, if used
destination S3 bucketThe source export bucket must be in the source Region. The destination seed bucket must be in the destination Region. Test ElastiCache service access to both buckets before the outage.
执行前放行#
先填写 变更执行记录。本路径只适用支持导出备份的 node-based 集群;数据分层等限制按 官方导出条件 核对。提前演练相同版本、分片/槽位、模块/数据类型与目标容量的导入,记录耗时;不要迁移时顺便改变拓扑或跨不兼容引擎版本。
明确数据角色:可重建缓存可以按业务方案重建;会话、锁、限流计数或队列状态不能当作可随意丢弃的缓存。预先确定停机期内键过期的影响和验收允许差异。源/目标 TLS、ACL、私网连通和管理身份在停写前验证。
3. Check Current Data Size#
Connect to the source primary endpoint with the required TLS/ACL options.
Current key count for one primary/database:
valkey-cli --tls -h SOURCE-PRIMARY-ENDPOINT -p 6379 DBSIZEKey count by logical database:
valkey-cli --tls -h SOURCE-PRIMARY-ENDPOINT -p 6379 INFO keyspaceMemory size:
valkey-cli --tls -h SOURCE-PRIMARY-ENDPOINT -p 6379 INFO memory | egrep '^(used_memory|used_memory_human|used_memory_dataset|used_memory_dataset_perc|used_memory_rss):'used_memory_dataset:
best in-memory estimate of key/value dataset bytes
used_memory:
dataset plus Valkey allocator/internal overhead
used_memory_rss:
operating-system resident memory
not the migration payload size
DBSIZE / INFO keyspace:
current key countFor cluster mode enabled, query every primary shard and sum DBSIZE and used_memory_dataset. Do not add replica nodes because they contain duplicate data.
List primary shard endpoints:
aws elasticache describe-replication-groups --profile "${SOURCE_PROFILE}" --region "${SOURCE_REGION}" --replication-group-id "${SOURCE_REPLICATION_GROUP}" --query 'ReplicationGroups[0].NodeGroups[].NodeGroupMembers[?CurrentRole==`primary`].ReadEndpoint' --output tableCloudWatch alternatives:
BytesUsedForCache:
cache-engine allocated bytes per node
CurrItems:
item count per node
DatabaseMemoryUsagePercentage:
memory utilization percentage, not byte sizeWhen using CloudWatch, sum primary nodes only. The final exported RDB file size can be smaller or different from used_memory_dataset because RDB serialization/compression and in-memory overhead differ. After export, use aws s3 ls --recursive --summarize for the actual S3 transfer size.
4. Stop Writes#
Stop application services, workers, scheduled jobs and admin scripts that write A1.
Keep writes stopped until the application has switched to B2. The final snapshot does not include changes written afterward.
5. Create Snapshot#
aws elasticache create-snapshot --profile "${SOURCE_PROFILE}" --region "${SOURCE_REGION}" --replication-group-id "${SOURCE_REPLICATION_GROUP}" --snapshot-name "${SNAPSHOT_NAME}"Check until Status=available:
aws elasticache describe-snapshots --profile "${SOURCE_PROFILE}" --region "${SOURCE_REGION}" --snapshot-name "${SNAPSHOT_NAME}" --show-node-group-config --query 'Snapshots[0].{Status:SnapshotStatus,Engine:Engine,Version:EngineVersion,NodeType:CacheNodeType,Shards:NodeSnapshots,KmsKeyId:KmsKeyId}'6. Export RDB To Account A S3#
The Account A S3 bucket must allow the ElastiCache backup export integration to write objects.
aws elasticache copy-snapshot --profile "${SOURCE_PROFILE}" --region "${SOURCE_REGION}" --source-snapshot-name "${SNAPSHOT_NAME}" --target-snapshot-name "${EXPORT_NAME}" --target-bucket "${SOURCE_BUCKET}"List exported RDB files:
aws s3api list-objects-v2 --bucket "$SOURCE_BUCKET" --prefix "$EXPORT_NAME" --profile "$SOURCE_PROFILE" --region "$SOURCE_REGION" --query 'Contents[].{Key:Key,Bytes:Size,Modified:LastModified}' --output tableCluster mode enabled can export multiple shard RDB files. All files must be copied and imported.
等待本次导出完成,将文件清单与快照的 NodeSnapshots/分片信息逐一核对;不能仅凭桶里出现一个文件就继续。导出名称每次唯一,清单需包含本次全部分片,不包含历史导出。
7. Copy RDB To Account B#
The account-b role used below needs s3:GetObject on the Account A export objects and s3:PutObject on the Account B prefix.
# Bash 数组:替换成已核对的本次全部对象键;不要扫描并复制桶内所有 RDB。
RDB_KEYS=('REPLACE_EXACT_EXPORT_KEY.rdb')
(
set -euo pipefail
(( ${#RDB_KEYS[@]} > 0 )) || exit 1
for key in "${RDB_KEYS[@]}"; do
[[ "$key" != REPLACE_* && "$key" == "$EXPORT_NAME"* && "$key" == *.rdb ]] || exit 1
aws s3 cp "s3://${SOURCE_BUCKET}/${key}" "s3://${DESTINATION_BUCKET}/${EXPORT_NAME}/${key}" --source-region "$SOURCE_REGION" --region "$DESTINATION_REGION" --profile "$DESTINATION_PROFILE" --only-show-errors
source_size=$(aws s3api head-object --bucket "$SOURCE_BUCKET" --key "$key" --profile "$DESTINATION_PROFILE" --region "$SOURCE_REGION" --query ContentLength --output text)
target_size=$(aws s3api head-object --bucket "$DESTINATION_BUCKET" --key "$EXPORT_NAME/$key" --profile "$DESTINATION_PROFILE" --region "$DESTINATION_REGION" --query ContentLength --output text)
[[ "$source_size" == "$target_size" ]] || exit 1
done
)上述块非零退出立即停止。字节数相同只是传输检查;关键文件另比较可用的同算法校验和,导入后仍需业务数据验收。源对象在复制期间保持不可变。
Verify destination files:
aws s3 ls "s3://${DESTINATION_BUCKET}/${EXPORT_NAME}/" --profile "${DESTINATION_PROFILE}" --region "${DESTINATION_REGION}" --recursiveAccount B must own the destination objects. The Account B ElastiCache service must have permission to read every RDB object and decrypt it when S3 uses a customer managed KMS key.
8. Create B2 From RDB#
Do not create B2 beforehand. Use the destination RDB object ARN, not an s3:// URL.
Example for cluster mode disabled / one shard:
RDB_ARN="arn:aws:s3:::${DESTINATION_BUCKET}/${EXPORT_NAME}/${RDB_KEYS[0]}"
aws elasticache create-replication-group --profile "${DESTINATION_PROFILE}" --region "${DESTINATION_REGION}" --replication-group-id "${DESTINATION_REPLICATION_GROUP}" --replication-group-description 'Migrated from Account A A1' --engine valkey --engine-version TARGET-COMPATIBLE-VALKEY-VERSION --cache-node-type cache.r7g.large --num-node-groups 1 --replicas-per-node-group 1 --automatic-failover-enabled --multi-az-enabled --cache-subnet-group-name account-b-valkey-subnets --cache-parameter-group-name account-b-valkey-parameters --security-group-ids sg-0123456789abcdef0 --at-rest-encryption-enabled --kms-key-id arn:aws:kms:ap-southeast-1:222222222222:key/DESTINATION-KEY-ID --transit-encryption-enabled --snapshot-arns "${RDB_ARN}"If ACL user groups are required, add:
--user-group-ids account-b-valkey-usersFor cluster mode enabled, pass every shard RDB ARN to --snapshot-arns and preserve the tested shard/slot topology. Do not restore a multi-shard export with --num-node-groups 1.
Wait for B2:
aws elasticache wait replication-group-available --profile "${DESTINATION_PROFILE}" --region "${DESTINATION_REGION}" --replication-group-id "${DESTINATION_REPLICATION_GROUP}"Get endpoint:
aws elasticache describe-replication-groups --profile "${DESTINATION_PROFILE}" --region "${DESTINATION_REGION}" --replication-group-id "${DESTINATION_REPLICATION_GROUP}" --query 'ReplicationGroups[0].{Status:Status,ClusterEnabled:ClusterEnabled,ConfigurationEndpoint:ConfigurationEndpoint,NodeGroups:NodeGroups}'9. Validate And Cut Over#
Connect with the same TLS/ACL mode required by B2, then check:
PING
DBSIZE
sample GET/HGETALL/LRANGE/SMEMBERS/ZRANGE/XINFO
sample PTTL
INFO keyspace
INFO memoryTTL continues to elapse during snapshot/copy/restore. A key can expire before B2 becomes available; this is expected.
Cut over:
1. keep A1 writes stopped
2. update application endpoint/secret to B2
3. restart client connection pools
4. run read/write/delete smoke tests
5. resume writes only on B2
6. monitor errors, latency, memory and evictionsBefore B2 accepts writes, rollback can point back to frozen A1. After B2 accepts writes, A1 is stale and rollback requires accepting state loss or performing another migration.
停止、恢复与结束#
| 信号 | 必须采取的动作 |
|---|---|
| 仍有源写入、快照未完成、分片文件缺失或导入失败 | 保持目标隔离,不切入口;源恢复写入后必须重做最终快照 |
| 键数量或 TTL 差异超出预定过期模型,类型/业务样本不符 | 停止放行,区分自然过期与迁移缺失,不以 PING 成功替代验收 |
| ACL/TLS、槽位路由、内存/驱逐或业务错误率不达标 | 停在目标验收阶段,修复配置或按停机预算决策 |
| 目标未写入而需取消 | 确认源仍能正确服务、目标隔离,再恢复源;锁/会话需考虑停机期间自然过期 |
| 目标已写入,包括测试请求 | 冻结并保存两侧状态;按反向迁移或经业务确认的数据补偿方案处理,不直接指回源 |
验收覆盖应用实际使用的每个逻辑库/分片、代表性键类型和剩余 TTL;以真实客户端做隔离测试键的写/读/删除,再检查业务会话或队列语义。观察错误率、延迟、内存、驱逐和连接数达到预先阈值后才结束。旧集群、快照、导出文件保留到约定恢复期结束;再按清单撤销跨账号授权和临时凭据。
10. Checklist#
[ ] node-based ElastiCache Valkey confirmed
[ ] Account B subnet/security/parameter/KMS/user-group resources prepared
[ ] source and destination S3 buckets are in their cache Regions
[ ] ElastiCache export/import S3 permissions tested
[ ] all A1 writers stopped
[ ] final snapshot status = available
[ ] every RDB shard copied to Account B
[ ] B2 created with compatible version/topology/capacity
[ ] key samples and TTL validated
[ ] application switched and connection pools restarted
[ ] only B2 accepts writes after cutover