yoloMiss
V2EX  ›  Redis

请大佬指点一下, redis 模糊匹配 key 查询缓慢问题

  •  
  •   yoloMiss · Mar 28, 2022 · 4304 views
    This topic created in 1532 days ago, the information mentioned may be changed or developed.

    起因--->最近接手的项目,有个需求需要通过 redis 做数据缓存,需要缓存当天和昨天的共二十几万条左右的数据。

    问题--->起初项目刚开始跑的时候没问题,过了一段时间后发现前端拿不到 redis 的数据了,排查程序日志发现全部请求超时了;遂排查 redis 是否有问题;发现 redis 占用 cpu 百分之百。通过 slowlog 排查发现所有占用 redis 的命令都是 keys 123* 做的数据查询。

    尝试解决--->替换 keys 命令匹配,使用 scan 进行扫描;并通过程序 log 观察匹配占用时间;发现 cup 占用率下来了,但是 scan 命令扫描比 keys 命令的扫描时间还要长。

    请问各位大佬该怎么解决这个问题。

    19 replies    2022-07-07 00:59:36 +08:00
    Jooooooooo
        1
    Jooooooooo  
       Mar 28, 2022
    分成多个 key 然后并行去查这些 key.
    crysislinux
        2
    crysislinux  
       Mar 28, 2022 via Android
    改变实现逻辑去掉 keys 调用。谁在 production 用 keys 谁挨打。楼上说的并行没用
    cweijan
        3
    cweijan  
       Mar 28, 2022
    你总不会一下子获取 20 万条数据吧, 拿一部分数据就行了
    ch2
        4
    ch2  
       Mar 28, 2022
    戒掉"我要用 keys 做模糊查询"这个想法
    用更复杂的机制间接实现你的想法
    zakokun
        5
    zakokun  
       Mar 28, 2022
    1. 绝对禁止使用 keys
    2. 写入 key 的时候记录下 key 名,然后在获取的时候,通过记录的 key 名,使用 MGET key1 key2 key3... 获取
    zakokun
        6
    zakokun  
       Mar 29, 2022
    @zakokun 当然这里 MGET 分批去获取,比如一次 1000 个 key 。或者使用 redis 的 pipline
    rockyliang
        7
    rockyliang  
       Mar 29, 2022
    1 )并发量不高的话改为用 MySQL 存储,只要建立好索引,像 123*这种模式的匹配,十几二十万的数据量完全撑得住
    2 )上 ElasticSearch
    GeruzoniAnsasu
        8
    GeruzoniAnsasu  
       Mar 29, 2022   ❤️ 1
    随手一搜: https://www.cnblogs.com/yinkw/p/redis_keys.html

    在 kv db 里全文扫描是否搞错了什么? 这样还不如 sqlite :memory: 呢
    night98
        9
    night98  
       Mar 29, 2022
    1.为啥会有这种需求?
    2. 能不能在数据生成的时候基于需求扔到对应 list 里去,比如 123* 的 string 放到 123 的 list 里面
    3. 换其他服务处理,比如 es ,数据量不大直接 mysql
    CEBBCAT
        10
    CEBBCAT  
       Mar 29, 2022
    zhs227
        11
    zhs227  
       Mar 29, 2022
    产生环境使用 keys 会导致灾难性后果。
    james2013
        12
    james2013  
       Mar 29, 2022
    1.使用 mysql 建 1 张新表,这个表只保存当天和昨天的数据
    2.将查询结果根据查询条件进行短时间缓存
    zmal
        13
    zmal  
       Mar 29, 2022
    怎么敢在生产环境用 keys ,要丢饭碗的啊
    zmal
        14
    zmal  
       Mar 29, 2022
    redis 内部是一个伪单线程实现,一个 keys 会阻塞后面所有的查询,导致全部超时。
    raptor
        15
    raptor  
       Mar 29, 2022
    模糊查询请使用 ES 集群,redis 不是这样用的
    sadfQED2
        16
    sadfQED2  
       Mar 29, 2022 via Android
    生产环境直接禁用 keys 命令,谁服务挂了就喷谁
    earneet
        17
    earneet  
       Mar 29, 2022
    对 key 维护一个字典树,需要模糊的时候先从字典树里找到具体的 key ,再去查
    DarkFaith
        18
    DarkFaith  
       Mar 29, 2022
    keys 的实现可以粗略的理解为遍历全部键,找到所有匹配的键然后全部返回。
    scan 的实现可以粗略的理解为分批次遍历,遍历完一部分后立即返回,然后开始下一次遍历。

    遍历是 O(n)的,也就是随着键的增多,消耗的时间是线性增加的。

    这个时候需要更高效的查询方法。

    需要分析存储的键是否可以 Hash ,如果可以 hash ,则可以使用 hash map 来存储数据。如果键是需要范围查询的,比如 top_n ,比如时间等等,可以采用 zset 来存储。
    erquiasz0825
        19
    erquiasz0825  
       Jul 7, 2022
    scan 难道不耗费 cpu 吗,可能就 100% 了
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   6136 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 96ms · UTC 03:11 · PVG 11:11 · LAX 20:11 · JFK 23:11
    ♥ Do have faith in what you're doing.