Cut over: migrate from Redis to KiviDB

The order is the same whichever method follows the writes (replication, RedisShake sync, or a live copy tool).

Cutover runbook

The order is the same whichever method follows the writes (replication, RedisShake sync, or a live copy tool).

  1. Rehearse. Run the whole move against a copy, with your application's test suite pointed at KiviDB. Note how long the full copy takes.

  2. Start the copy and wait until it follows the writes: master_link_status:up and equal offsets for replication, syncing aof, diff=[0] for RedisShake.

  3. Verify with the script below while writes continue. A few keys written in the last second may differ; nothing else should.

  4. Lower your client timeouts and retries if they are long, so the switch is quick.

  5. Stop writes to Redis. Either stop the writers, or block them at the server:

    redis-cli -h redis.internal CLIENT PAUSE 60000 WRITE
    

    CLIENT PAUSE … WRITE (Redis 6.2+) holds every write for up to 60 seconds, while reads keep working and replication keeps flowing.

  6. Check the last writes arrived: offsets equal again, or diff=[0] again. Run DBSIZE on both.

  7. Promote KiviDB (replication only):

    redis-cli -p 6380 REPLICAOF NO ONE
    

    With RedisShake, stop the process.

  8. Point the clients at KiviDB: change the setting and restart or reload, or move the DNS name the clients use. Clients that were held by CLIENT PAUSE time out and reconnect.

  9. Verify again and watch the application's error rate and KiviDB's log.

  10. Keep Redis running, without writes, until you are sure. When the pause runs out, Redis accepts writes again, so make sure nothing still points at it: INFO clients shows connected_clients, and CLIENT LIST shows who.

Rollback. Until clients write to KiviDB, rolling back is CLIENT UNPAUSE on Redis and pointing the clients back. Decide before the switch how you would roll back after that, because the way back is narrower than the way in:

  • A Redis or Valkey replica of KiviDB doesn't work: the full sync fails with Wrong signature trying to load DB from file, because KiviDB sends its own snapshot format. RedisShake can't read it either, and Redis and Valkey refuse KiviDB's DUMP payloads (DUMP payload version or checksum are wrong), so scan_reader and RIOT's default mode copy nothing.
  • RIOT with --struct copies KiviDB back with ordinary commands. It reads with Lua scripts, so it needs the lua or full build on the KiviDB side; against a build without Lua it copies nothing and still exits with status 0, so check the result with the verify script. Stream consumer groups and hash field expiry are not copied.
  • HyperLogLogs written by KiviDB are in KiviDB's own layout unless KiviDB runs with --hll-write-format redis; Redis rejects them otherwise (INVALIDOBJ Corrupted HLL object). Set it from the start if you might roll back.
riot replicate redis://kividb.internal:6380 redis://redis.internal:6379 \
  --source-pass "$KIVIDB_PASSWORD" --target-pass "$REDIS_PASSWORD" \
  --struct --compare NONE

So until you are confident, keep the way back short: switch reads first and keep writing to Redis, or have the application write to both for a while (see dual-write), and keep Redis intact.

After the switch

  • Watch KiviDB's log for warnings: each says what to do, and the errors page explains them.
  • Keep the old Redis, without writes, until you are sure.
  • To compare throughput on your own hardware first, the benchmark guide runs the same tests we publish.