# Migrating Redis databases There are two templates examples in this repo: - `redis` - basic non-persistent template. It is good for review-apps or staging or where no persistence is required - `redis2` - basic persistent template. Good for production where persistence is needed, but cluster is overkill. ## Option 1: use SLAVEOF (easier way) 1. create a redis workload that will accept data 2. execute `SLAVEOF source_host source_port`, if needed use `masterauth` to provide auth details 3. wait for replication to pick up all changes (usually quickly), use `INFO` or `DBSIZE` to check progress 4. stop app completely and ensure nothing is writing to any of redises 5. execute `SLAVEOF no one` to disconnect replication 6. switch `REDIS_URL` in the app to point to new server 7. start the app ## Option 2: use Redis-RIOT (harder way, where option 1 is not possible) ### General considerations: 1. Heroku uses self-signed TLS certificates, which are not verifiable. It needs special handling by setting The tool that satisfies those criteria is [Redis-RIOT](https://developer.redis.com/riot/riot-redis/index.html) 2. We are moving to private Redis that don't have a public URL, so have to do it from a Control Plane GVC container. The tool that satisfies those criteria is [Redis-RIOT](https://developer.redis.com/riot/riot-redis/index.html) ### Heroku Redis: As Redis-RIOT says, master redis should have keyspace-notifications set to `KA` to be able to do live replication. To do that: ```sh heroku redis:keyspace-notifications -c KA -a my-app ``` Connect to heroku Redis CLI: ```sh heroku redis:cli -a my-app ``` ### Control Plane Redis: Connect to Control Plane Redis CLI: ```sh # open cpflow interactive shell cpflow run bash -a my-app # install redis CLI if you don't have it in Docker apt-get update apt-get install redis -y # connect to local cloud Redis redis-cli -u MY_CONTROL_PLANE_REDIS_URL -p 6379 ``` ### Useful Redis CLI commands: Quick-check keys qty: ``` info keyspace # Keyspace db0:keys=9496,expires=2941,avg_ttl=77670114535 ``` ### Create a Control Plane sync workload ``` name: riot-redis suspend: true min/max scale: 1/1 firewall: all firewalls off image: fieldengineering/riot-redis CPU: 1 Core RAM: 1 GB command args: --info -u rediss://...your_heroku_redis_url... --tls-verify=NONE replicate -h ...your_control_plane_redis_host... --mode live ``` ### Sync process 1. open 1st terminal window with heroku redis CLI, check keys qty 2. open 2nd terminal window with controlplane redis CLI, check keys qty 3. start sync container 4. open logs with `cpflow logs -a my-app -w riot-redis` 4. re-check keys sync qty again 5. stop sync container Result: ``` Setting commit interval to default value (1) Setting commit interval to default value (1) Job: [SimpleJob: [name=snapshot-replication]] launched with the following parameters: [{}] Executing step: [snapshot-replication] Scanning 0% ╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0/8891 (0:00:00 / ?)Job: [SimpleJob: [name=scan-reader]] launched with the following parameters: [{}] Executing step: [scan-reader] Scanning 61% ━━━━━━━━━━━━━━━━╸━━━━━━━━━━ 5460/8891 (0:00:07 / 0:00:04) 780.0/sStep: [scan-reader] executed in 7s918ms Closing with items still in queue Job: [SimpleJob: [name=scan-reader]] completed with the following parameters: [{}] and the following status: [COMPLETED] in 7s925ms Scanning 100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━ 9482/9482 (0:00:11 / 0:00:00) 862.0/s Step: [snapshot-replication] executed in 13s333ms Executing step: [verification] Verifying 0% ╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0/8942 (0:00:00 / ?)Job: [SimpleJob: [name=RedisItemReader]] launched with the following parameters: [{}] Executing step: [RedisItemReader] Verifying 2% ╺━━━━━━━━━━━━━━━━━ 220/8942 (0:00:00 / 0:00:19) ?/s >0 T0 ≠Step: [RedisItemReader] executed in 7s521ms Closing with items still in queue Job: [SimpleJob: [name=RedisItemReader]] completed with the following parameters: [{}] and the following status: [COMPLETED] in 7s522ms Verification completed - all OK Step: [verification] executed in 7s776ms Job: [SimpleJob: [name=snapshot-replication]] completed with the following parameters: [{}] and the following status: [COMPLETED] in 21s320ms ``` Total sync time ~1min