Skip to content

Commit 4edf1dd

Browse files
author
Jamie Curnow
committed
Use scan instead of keys for large datasets
1 parent f1bcb0a commit 4edf1dd

File tree

2 files changed

+51
-37
lines changed

2 files changed

+51
-37
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,6 @@ go get github.com/jc21/redis-migrator
7070

7171
```bash
7272
git clone https://github.com/jc21/redis-migrator && cd redis-migrator
73-
go build -v -ldflags="-X main.version=1.0.1" -o bin/redis-migrator cmd/redis-migrator/main.go
73+
go build -ldflags="-X main.version=1.0.1" -o bin/redis-migrator cmd/redis-migrator/main.go
7474
./bin/redis-migrator -h
7575
```

pkg/migrator/migrate.go

Lines changed: 50 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -26,51 +26,65 @@ func DoMigration(sourceClient, destinationClient *redis.Client, keyFilter, keyPr
2626
os.Exit(1)
2727
}
2828

29-
logger.Info("Migration running...")
29+
logger.Info("Migration running, each dot is 1,000 keys, each row is 50,000 keys")
3030

31-
cmd := sourceClient.Keys(helpers.Ctx, keyFilter)
32-
if cmd.Err() != nil {
33-
logger.Error("SOURCE: %s", cmd.Err())
34-
os.Exit(1)
35-
}
36-
37-
keys, err := cmd.Result()
38-
if err != nil {
39-
logger.Error("SOURCE: %s", err)
40-
os.Exit(1)
41-
}
31+
var cursor uint64
32+
var n int
4233

4334
counter := 0
4435
skipped := 0
45-
for _, sourceKey := range keys {
46-
destinationKey := keyPrefix + sourceKey
47-
48-
// read from source
49-
typeCmd := sourceClient.Type(helpers.Ctx, sourceKey)
50-
keyType := typeCmd.Val()
51-
ttl := sourceClient.TTL(helpers.Ctx, sourceKey).Val()
52-
53-
logger.Trace("Key '%s' type '%s' ttl: %v destination: '%s'", sourceKey, keyType, ttl, destinationKey)
54-
55-
switch keyType {
56-
case "string":
57-
copyString(sourceClient, destinationClient, sourceKey, destinationKey, ttl)
58-
case "hash":
59-
copyHash(sourceClient, destinationClient, sourceKey, destinationKey)
60-
case "list":
61-
copyList(sourceClient, destinationClient, sourceKey, destinationKey)
62-
case "none":
63-
// Key does not exist, or at least not anymore.
64-
skipped++
65-
default:
66-
logger.Error("Key type not yet supported: %s", keyType)
67-
logger.Error("Migration was NOT completed!")
36+
dots := 0
37+
38+
for {
39+
var keys []string
40+
var scanErr error
41+
keys, cursor, scanErr = sourceClient.Scan(helpers.Ctx, cursor, keyFilter, 1000).Result()
42+
if scanErr != nil {
43+
logger.Error("Scan Error: %+v", scanErr)
6844
os.Exit(1)
6945
}
7046

71-
counter++
47+
for _, sourceKey := range keys {
48+
destinationKey := keyPrefix + sourceKey
49+
50+
// read from source
51+
typeCmd := sourceClient.Type(helpers.Ctx, sourceKey)
52+
keyType := typeCmd.Val()
53+
ttl := sourceClient.TTL(helpers.Ctx, sourceKey).Val()
54+
55+
logger.Trace("Key '%s' type '%s' ttl: %v destination: '%s'", sourceKey, keyType, ttl, destinationKey)
56+
57+
switch keyType {
58+
case "string":
59+
copyString(sourceClient, destinationClient, sourceKey, destinationKey, ttl)
60+
case "hash":
61+
copyHash(sourceClient, destinationClient, sourceKey, destinationKey)
62+
case "list":
63+
copyList(sourceClient, destinationClient, sourceKey, destinationKey)
64+
case "none":
65+
// Key does not exist, or at least not anymore.
66+
skipped++
67+
default:
68+
logger.Error("Key type not yet supported: %s", keyType)
69+
logger.Error("Migration was NOT completed!")
70+
os.Exit(1)
71+
}
72+
73+
counter++
74+
}
75+
76+
fmt.Print(".")
77+
dots++
78+
n += len(keys)
79+
if cursor == 0 {
80+
break
81+
}
82+
if dots%50 == 0 {
83+
fmt.Print("\n")
84+
}
7285
}
7386

87+
fmt.Print("\n")
7488
logger.Info("Migration completed with %d keys, %d skipped :)", counter, skipped)
7589
os.Exit(0)
7690
}

0 commit comments

Comments
 (0)