V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
qqqasdwx
V2EX  ›  Redis

关于 redis 的 scan 命令并发执行的问题,望解答

  •  
  •   qqqasdwx · 2020-12-15 23:59:09 +08:00 · 2963 次点击
    这是一个创建于 1436 天前的主题,其中的信息可能已经有所发展或是发生改变。

    reids 推荐在生产环境中使用scan命令来代替keys命令获取所有 key,我有些疑惑,望各位大佬解答🙏。

    前提:redis 中 key 的数量一直在频繁变化

    我已经测试了单连接快速多次执行scan 0,返回的游标是相同的,那么问题是:

    1. 如果两个连接同时发送scan 0命令,redis 返回的游标是否可能相同(因 redis 是单线程,所以响应肯定有先有后,所以这个问题是:临近的两次响应,返回的游标是否可能相同)?
    2. 进阶问题:多个连接中多次执行scan命令,返回游标是否可能相同?
    3. 如果上述两个问题中会出现相同游标,那么如何保证两个连接获取到相同数量级的 key ?

    如图

    像这样,每次 scan 一万条数据,会不会出现 [连接 2 ] 获取的 key 比 [连接 1 ] 少两万个呢?极限情况, [连接 1 ] 已经扫描到数据结尾,会不会导致 [连接 2 ] 只能获取两万个 key 呢?

    提前感谢各位大佬,我查了半天,只能查到just do my best,我可以允许 scan 出来的 key 多一点少一点,但也不能少太多吧

    13 条回复    2021-03-02 23:46:34 +08:00
    lpts007
        1
    lpts007  
       2020-12-16 06:38:25 +08:00 via Android
    不知道说啥,scan 和两个连接有啥关系?
    teek
        2
    teek  
       2020-12-16 08:59:21 +08:00
    取决于你数据变动情况。redis.io/commands/scan#scan-guarantees
    yRebelHero
        3
    yRebelHero  
       2020-12-16 09:30:48 +08:00
    redis 里的 key 都是存储在一个字典里的,有点类似于 Java 里的 HashMap,一维是数组,二维是链表,游标返回的就是第一维数组的位置索引,而且它的遍历不是从一维数组的第 0 位一直遍历到末尾,而是用的一种高位进位加法来遍历。举个例子,普通的是 0->1->2->3,高位进位加法是 0 -> 8 -> 4 -> 12 -> 2 这样的。
    yRebelHero
        4
    yRebelHero  
       2020-12-16 09:34:58 +08:00
    不好意思,先发出去了,接上文。

    遍历的时候如果有数据修改,改动后的数据能不能遍历到是不一定的。

    既然你的问题的前提是:key 的数量时一直频繁变化的。那么问题 1 、2,返回的游标可能不一样,既然上面两个问题不相同,第 3 个问题就没法回答你了。
    xuanbg
        5
    xuanbg  
       2020-12-16 09:58:52 +08:00
    自己做一个 key 管理,Redis 已经很忙很辛苦了,就不要再为难 Redis 了。。。
    lithium4010
        6
    lithium4010  
       2020-12-16 11:47:59 +08:00
    你为啥要拿所有的 key ? key 很大的时候, 它这个就没有设计这种使用场景我理解
    lithium4010
        7
    lithium4010  
       2020-12-16 11:48:23 +08:00
    @lithium4010 我是只 key 的数量很大的时候
    lithium4010
        8
    lithium4010  
       2020-12-16 11:48:40 +08:00
    我是指..
    qqqasdwx
        9
    qqqasdwx  
    OP
       2020-12-16 18:07:35 +08:00
    @lpts007 和两个连接确实没什么关系,其实就是想问 scan 的游标是怎么维护的,多次扫描并行存在时会不会相互影响
    qqqasdwx
        10
    qqqasdwx  
    OP
       2020-12-16 18:20:48 +08:00
    @yRebelHero 谢谢您的耐心解答,那么用具体场景来举例子,比方说有两个用户查询全部 key,假设页面无限加载,一次 scan 的 count 设为 1,redis 里数量级相对固定(比如 2kw 数据,上下浮动 1w,但 key 会频繁变动,大量删除大量增加,但总数维持在 2kw ),那么如果出现了相同游标,会不会出现一个极限情况,用户 1 最终刷出了 2kw 数据,用户 2 只能刷出 2 条数据?
    qqqasdwx
        11
    qqqasdwx  
    OP
       2020-12-16 18:29:48 +08:00
    @lithium4010 比如淘宝商品页做无限加载,每秒都有大量商家上货,也有大量商家下架,不能说一个用户最终能看到全部商品,而另一个用户只能看到两页吧,当然这只是我假想了一个使用场景,想问的是在 redis 不维护 session 的情况下如何保证能扫描到大部分 key
    yRebelHero
        12
    yRebelHero  
       2020-12-16 20:16:37 +08:00
    @qqqasdwx 其实不是很明白你描述的具体场景,但应该不会这么极端的,毕竟 key 在字典里都是经过 hash 了一次的,肯定是比较均匀地分布,不会那么极端的。
    huskyui
        13
    huskyui  
       2021-03-02 23:46:34 +08:00
    可以看一下 https://tech.meituan.com/2018/07/27/redis-rehash-practice-optimization.html
    文章里面的 Redis 使用 Scan 清理 Key 由于 Rehash 导致清理数据不彻底
    今天刚看到 dict 这边的 scan 命令
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2705 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 15:21 · PVG 23:21 · LAX 07:21 · JFK 10:21
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.