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

2022-03-28 23:27:45 +08:00
 yoloMiss

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

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

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

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

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

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

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

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

需要分析存储的键是否可以 Hash ,如果可以 hash ,则可以使用 hash map 来存储数据。如果键是需要范围查询的,比如 top_n ,比如时间等等,可以采用 zset 来存储。
erquiasz0825
2022-07-07 00:59:36 +08:00
scan 难道不耗费 cpu 吗,可能就 100% 了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/843504

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX