• redis中使用SCAN代替KEYS


    前言

    由于redis的keys命令是线上禁用,所以就有了SCANSSCANHSCANZSCAN四个命令。
    但是这四个命令也不是每次返回全部匹配结果,因此需要一遍遍执行下去,而且每次返回的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等方案,虽然可以达到效果,但是使用上是存在一点不方便的,总之应该尽量避免这些逻辑。

    作者:janbar
    本文版权归作者和博客园所有,欢迎转载,转载请标明出处。喜欢我的文章请 [关注我] 吧。
    如果您觉得本篇博文对您有所收获,可点击 [推荐] [收藏] ,或到右侧 [打赏] 里请我喝杯咖啡,非常感谢。
  • 相关阅读:
    nyoj 599-奋斗的小蜗牛 (double ceil(); (temp
    nyoj 596-谁是最好的Coder (greater, less)
    nyoj 517-最小公倍数 (python range(start, end) range(length))
    用深度学习预测专业棋手走法
    阿里AI设计师一秒出图,小撒连连惊呼,真相是...
    想成为数据科学家?先做到这6点吧!
    Kubernetes 弹性伸缩全场景解析 (一)- 概念延伸与组件布局
    机器学习基础:(Python)训练集测试集分割与交叉验证
    Data Lake Analytics + OSS数据文件格式处理大全
    聊聊Flexbox布局中的flex的演算法
  • 原文地址:https://www.cnblogs.com/janbar/p/15191978.html
Copyright © 2020-2023  润新知