
起因--->最近接手的项目,有个需求需要通过 redis 做数据缓存,需要缓存当天和昨天的共二十几万条左右的数据。
问题--->起初项目刚开始跑的时候没问题,过了一段时间后发现前端拿不到 redis 的数据了,排查程序日志发现全部请求超时了;遂排查 redis 是否有问题;发现 redis 占用 cpu 百分之百。通过 slowlog 排查发现所有占用 redis 的命令都是 keys 123* 做的数据查询。
尝试解决--->替换 keys 命令匹配,使用 scan 进行扫描;并通过程序 log 观察匹配占用时间;发现 cup 占用率下来了,但是 scan 命令扫描比 keys 命令的扫描时间还要长。
请问各位大佬该怎么解决这个问题。
1 Jooooooooo 2022-03-28 23:36:34 +08:00 分成多个 key 然后并行去查这些 key. |
2 crysislinux 2022-03-28 23:38:54 +08:00 via Android 改变实现逻辑去掉 keys 调用。谁在 production 用 keys 谁挨打。楼上说的并行没用 |
3 cweijan 2022-03-28 23:43:04 +08:00 你总不会一下子获取 20 万条数据吧, 拿一部分数据就行了 |
4 ch2 2022-03-28 23:52:41 +08:00 戒掉"我要用 keys 做模糊查询"这个想法 用更复杂的机制间接实现你的想法 |
5 zakokun 2022-03-28 23:59:15 +08:00 1. 绝对禁止使用 keys 2. 写入 key 的时候记录下 key 名,然后在获取的时候,通过记录的 key 名,使用 MGET key1 key2 key3... 获取 |
7 rockyliang 2022-03-29 00:07:45 +08:00 1 )并发量不高的话改为用 MySQL 存储,只要建立好索引,像 123*这种模式的匹配,十几二十万的数据量完全撑得住 2 )上 ElasticSearch |
8 GeruzoniAnsasu 2022-03-29 01:37:07 +08:00 |
9 night98 2022-03-29 01:42:37 +08:00 1.为啥会有这种需求? 2. 能不能在数据生成的时候基于需求扔到对应 list 里去,比如 123* 的 string 放到 123 的 list 里面 3. 换其他服务处理,比如 es ,数据量不大直接 mysql |
10 CEBBCAT 2022-03-29 01:47:55 +08:00 |
11 zhs227 2022-03-29 08:24:22 +08:00 产生环境使用 keys 会导致灾难性后果。 |
12 james2013 2022-03-29 09:10:58 +08:00 1.使用 mysql 建 1 张新表,这个表只保存当天和昨天的数据 2.将查询结果根据查询条件进行短时间缓存 |
13 zmal 2022-03-29 09:17:06 +08:00 怎么敢在生产环境用 keys ,要丢饭碗的啊 |
14 |
15 raptor 2022-03-29 09:53:23 +08:00 模糊查询请使用 ES 集群,redis 不是这样用的 |
16 sadfQED2 2022-03-29 11:45:36 +08:00 via Android 生产环境直接禁用 keys 命令,谁服务挂了就喷谁 |
17 earneet 2022-03-29 12:21:41 +08:00 对 key 维护一个字典树,需要模糊的时候先从字典树里找到具体的 key ,再去查 |
18 DarkFaith 2022-03-29 15:45:52 +08:00 keys 的实现可以粗略的理解为遍历全部键,找到所有匹配的键然后全部返回。 scan 的实现可以粗略的理解为分批次遍历,遍历完一部分后立即返回,然后开始下一次遍历。 遍历是 O(n)的,也就是随着键的增多,消耗的时间是线性增加的。 这个时候需要更高效的查询方法。 需要分析存储的键是否可以 Hash ,如果可以 hash ,则可以使用 hash map 来存储数据。如果键是需要范围查询的,比如 top_n ,比如时间等等,可以采用 zset 来存储。 |
19 erquiasz0825 2022-07-07 00:59:36 +08:00 scan 难道不耗费 cpu 吗,可能就 100% 了 |