2
0
Эх сурвалжийг харах

Add redis-to-valkey migratior

FreddleSpl0it 6 сар өмнө
parent
commit
0698159f07

+ 8 - 0
data/Dockerfiles/valkeymigrator/Dockerfile

@@ -0,0 +1,8 @@
+FROM python:3.13.2-alpine3.21
+
+WORKDIR /app
+
+COPY migrate.py /app/migrate.py
+RUN pip install --no-cache-dir redis
+
+CMD ["python", "/app/migrate.py"]

+ 78 - 0
data/Dockerfiles/valkeymigrator/migrate.py

@@ -0,0 +1,78 @@
+import subprocess
+import redis
+import time
+import os
+
+# Container names
+SOURCE_CONTAINER = "redis-old-mailcow"
+DEST_CONTAINER = "valkey-mailcow"
+VALKEYPASS = os.getenv("VALKEYPASS")
+
+
+def migrate_redis():
+    src_redis = redis.StrictRedis(host=SOURCE_CONTAINER, port=6379, db=0, password=VALKEYPASS, decode_responses=False)
+    dest_redis = redis.StrictRedis(host=DEST_CONTAINER, port=6379, db=0, password=VALKEYPASS, decode_responses=False)
+
+    cursor = 0
+    batch_size = 100
+    migrated_count = 0
+
+    print("Starting migration...")
+
+    while True:
+        cursor, keys = src_redis.scan(cursor=cursor, match="*", count=batch_size)
+        keys_to_migrate = [key for key in keys if not key.startswith(b"PHPREDIS_SESSION:")]
+
+        for key in keys_to_migrate:
+            key_type = src_redis.type(key)
+            print(f"Import {key} of type {key_type}")
+
+            if key_type == b"string":
+                value = src_redis.get(key)
+                dest_redis.set(key, value)
+
+            elif key_type == b"hash":
+                value = src_redis.hgetall(key)
+                dest_redis.hset(key, mapping=value)
+
+            elif key_type == b"list":
+                value = src_redis.lrange(key, 0, -1)
+                for v in value:
+                    dest_redis.rpush(key, v)
+
+            elif key_type == b"set":
+                value = src_redis.smembers(key)
+                for v in value:
+                    dest_redis.sadd(key, v)
+
+            elif key_type == b"zset":
+                value = src_redis.zrange(key, 0, -1, withscores=True)
+                for v, score in value:
+                    dest_redis.zadd(key, {v: score})
+
+            # Preserve TTL if exists
+            ttl = src_redis.ttl(key)
+            if ttl > 0:
+                dest_redis.expire(key, ttl)
+
+            migrated_count += 1
+
+        if cursor == 0:
+            break  # No more keys to scan
+
+    print(f"Migration completed! {migrated_count} keys migrated.")
+
+    print("Forcing Valkey to save data...")
+    try:
+        dest_redis.save()  # Immediate RDB save (blocking)
+        dest_redis.bgrewriteaof()  # Rewrites the AOF file in the background
+        print("Data successfully saved to disk.")
+    except Exception as e:
+        print(f"Failed to save data: {e}")
+
+# Main script execution
+if __name__ == "__main__":
+    try:
+        migrate_redis()
+    finally:
+        pass

+ 52 - 0
helper-scripts/redis-to-valkey.sh

@@ -0,0 +1,52 @@
+#!/bin/bash
+
+SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
+source "${SCRIPT_DIR}/../mailcow.conf"
+
+VOLUME="${COMPOSE_PROJECT_NAME}_redis-vol-1"
+if ! docker volume inspect "$VOLUME" &>/dev/null; then
+    echo "Error: Docker volume '$VOLUME' does not exist. Nothing to migrate."
+    exit 1
+fi
+
+read -p "Do you want to proceed with the migration of your old redis data to valkey? (y/n) " CONFIRM
+if [[ ! "$CONFIRM" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
+    echo "Migration aborted."
+    exit 0
+fi
+
+# Run the old Redis container
+docker run -d --name redis-old-mailcow \
+    --restart always \
+    --network ${COMPOSE_PROJECT_NAME}_mailcow-network \
+    --hostname redis-old \
+    --volume ${VOLUME}:/data/ \
+    --volume ${SCRIPT_DIR}/../data/conf/valkey/valkey-conf.sh:/valkey-conf.sh:z \
+    --entrypoint "/bin/sh" \
+    -e VALKEYPASS="${VALKEYPASS}" \
+    redis:7.4.2-alpine -c "/valkey-conf.sh && redis-server /valkey.conf"
+
+
+# Wait for old Redis to be ready
+echo "Waiting for redis-old-mailcow to be ready..."
+until docker exec redis-old-mailcow redis-cli -a "$VALKEYPASS" ping | grep -q "PONG"; do
+    echo "Redis not ready yet..."
+    sleep 2
+done
+echo "redis-old-mailcow is ready!"
+
+# Run the migrate container
+docker run --rm --name valkeymigrator-mailcow \
+    --network ${COMPOSE_PROJECT_NAME}_mailcow-network \
+    -e VALKEYPASS="${VALKEYPASS}" \
+    mailcow/valkeymigrator:0.1
+
+echo "Migration completed!"
+docker stop redis-old-mailcow
+docker rm redis-old-mailcow
+
+read -p "Do you want to delete the old Redis volume? (y/n) " CONFIRM
+if [[ "$CONFIRM" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
+    docker volume rm "$VOLUME"
+    echo "Docker volume '$VOLUME' has been deleted."
+fi