Zero downtime Redis migration or upgrade
Tags: redis, devops
Published: 2024-01-27 07:08:11

I wrote about migrating the Redis database from AWS ElastiCache to another provider [a few years ago ](https://berislavbabic.com/how-to-migrate-redis-to-another-provider/). In my case it was Azure, but it doesn’t matter. I used a different, more _hands-on_ approach there, since AWS limits config commands on their instances (to make it harder to move away I guess). I’m gonna show you another, faster way of migrating data from one Redis instance to another with near zero downtime.

### Prerequisites
Let’s say you have 2 Redis instances set up, I’m gonna call them SOURCE and TARGET from now on. Those servers should be able to communicate with each other, at least on the 6379 (or whatever Redis port you are using). 


### Database replication

We are going to use `redis-cli` as our tool of choice here. Make sure the machine you are doing this from has access to both SOURCE and TARGET.  

On the TARGET instance, we tell it to act as a replica of the SOURCE by running: 
```
  REPLICAOF SOURCE 6379
```
 If you have password authentication set on the SOURCE, we need to provide the authentication option here as well 
```
MASTERAUTH SOURCE_PASSWORD
```
Give it a minute or two and then you can run 
```
INFO KEYSPACE
```
on both SOURCE and TARGET in parallel, to make sure the replication is running. Comparing the number of keys in each database is enough here. When you get the differences to be under 1% of the total keys, you can plan the next steps. The percentage depends on your application activity and how often it writes to Redis.

When you are certain the databases are in sync, we will turn of the read-only setting on the TARGET database. This isn’t recommended, but if you have a stable network connection between the databases, and are quick enough, nothing weird will happen. On the TARGET redis-cli we run 
```
CONFIG SET REPLICA-READ-ONLY NO
```
This allows us to write data to the replica independent of the SOURCE which will keep writing the incoming data and syncing it over to TARGET.

### Switch over to the new database

Next step is updating connection strings for your application. You replace the SOURCE with the TARGET (make sure you have updated authentication parameters so you can connect to the new db). If you can, run an isolated REPL instance to make sure your application can connect (this would be Rails console in my world). 

After you are 100% your application can connect to the new Redis database, do a service restart or deploy to get the instance(s) running with the new connection string. The read-only setting that we turned off will allow _old_ instances of the application to still write to the SOURCE and replicate the data to TARGET, and the new instances will write to TARGET so your migration is zero downtime (if your deploys are zero downtime, of course). 

After the services have restarted, make sure the old processes have ended and nothing is connected to SOURCE anymore. Then you can run 
```
REPLICAOF NO ONE
```
on the TARGET to promote it to master. You can clean up SOURCE after this step, but I would backup the database snapshot file, in case that you need to restore it later.