How to scan redis keys with golang using "SCAN" rather than "KEYS"

This is my code.

redisPool := redis.NewPool(func() (redis.Conn, error) {
        con, err := redis.Dial("tcp", *redisAddress)
        con.Do("SELECT", 0)
        if err != nil {
            return nil, err
        }
        return con, err
    }, *maxConnections)
    fmt.Println("Redis Connection Establ...!")
    con := redisPool.Get()
    data, err1 := con.Do("scan", "0")
    //data, err1 := con.Do("KEYS", "*")
    if err1 != nil {
        fmt.Println(err1)
    } else {
        fmt.Println(reflect.TypeOf(data))
        fmt.Println(data)
    }

my output is not on the line

+4
source share
1 answer

The thing about the SCAN command is that it does not just return a bunch of keys, but it returns the number of the "iterator" that you should put in the next SCAN call. therefore, the structure of the answer can be seen as

[ iterator, [k1, k2, ... k10] ]

You start with a call SCAN 0and in consecutive calls you need to call SCAN <iterator>.

Doing this with redigo is as follows (my error handling is wrong, but it just shows the idea):

// here we'll store our iterator value
iter := 0

// this will store the keys of each iteration
var keys []string
for {

    // we scan with our iter offset, starting at 0
    if arr, err := redis.MultiBulk(conn.Do("SCAN", iter)); err != nil {
        panic(err)
    } else {

        // now we get the iter and the keys from the multi-bulk reply
        iter, _ = redis.Int(arr[0], nil)
        keys, _ = redis.Strings(arr[1], nil)
    }

    fmt.Println(keys)

    // check if we need to stop...
    if iter == 0  {
        break
    }
}
+9
source

Source: https://habr.com/ru/post/1598553/


All Articles