前言
由于redis的keys命令是线上禁用,所以就有了
SCAN
、SSCAN
、HSCAN
和ZSCAN
四个命令。
但是这四个命令也不是每次返回全部匹配结果,因此需要一遍遍执行下去,而且每次返回的cursor
要作为下一个的参数。
因此查找也不太方便,我写了一个简单的方法,用来查找scan的所有结果。关于这几个命令可以参考【详细解释】
代码分享
|
package main |
|
|
|
import ( |
|
"errors" |
|
"flag" |
|
"fmt" |
|
"strings" |
|
|
|
"github.com/gomodule/redigo/redis" |
|
) |
|
|
|
func main() { |
|
addr := flag.String("addr", "redis://127.0.0.1:6379", "url") |
|
cmd := flag.String("cmd", "SCAN", "SCAN or SSCAN or HSCAN or ZSCAN") |
|
key := flag.String("key", "", "key") |
|
match := flag.String("match", "", "MATCH pattern") |
|
count := flag.Int("count", 10, "COUNT count") |
|
max := flag.Int("max", 1000, "max count") |
|
flag.Parse() |
|
|
|
err := scanHandle(*addr, *cmd, *key, *match, *count, *max) |
|
if err != nil { |
|
fmt.Println(err) |
|
} |
|
} |
|
|
|
func scanHandle(addr, cmd, key, match string, count, max int) error { |
|
switch cmd = strings.ToUpper(cmd); cmd { |
|
case "SCAN", "SSCAN", "HSCAN", "ZSCAN": |
|
default: |
|
return errors.New("cmd error") |
|
} |
|
|
|
c, err := redis.DialURL(addr) |
|
if err != nil { |
|
return err |
|
} |
|
defer c.Close() |
|
|
|
var ( |
|
i = 0 // cursor下标位置 |
|
cursor = 0 // 默认从0开始 |
|
args = make([]interface{}, 0, 5) |
|
) |
|
|
|
if cmd != "SCAN" { |
|
if key == "" { |
|
return errors.New(cmd + " must have key") |
|
} |
|
args = append(args, key) |
|
i++ |
|
} |
|
|
|
args = append(args, cursor) |
|
if match != "" { |
|
args = append(args, "MATCH", match) |
|
} |
|
if count <= 0 { |
|
count = 16 |
|
} |
|
args = append(args, "COUNT", count) |
|
|
|
for { |
|
args[i] = cursor |
|
res, err := redis.Values(c.Do(cmd, args...)) |
|
if err != nil { |
|
return err |
|
} |
|
|
|
var tmp []string |
|
_, err = redis.Scan(res, &cursor, &tmp) |
|
if err != nil { |
|
return err |
|
} |
|
|
|
if lt := len(tmp); lt > 0 { |
|
for _, v := range tmp { |
|
// 打印结果 |
|
fmt.Println(v) |
|
} |
|
|
|
if max -= lt; max <= 0 { |
|
break |
|
} |
|
} |
|
|
|
if cursor == 0 { |
|
break // 查询结束 |
|
} |
|
} |
|
return nil |
|
} |
总结
其实我们应该避免查找相关key,因为代码里面会保存相应的key,而且可以通过设置过期时间自动删除相关key。 不过redis提供了scan等方案,虽然可以达到效果,但是使用上是存在一点不方便的,总之应该尽量避免这些逻辑。