惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
Schneier on Security
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
T
Threat Research - Cisco Blogs
C
Cyber Attacks, Cyber Crime and Cyber Security
C
CXSECURITY Database RSS Feed - CXSecurity.com
A
Arctic Wolf
Security Latest
Security Latest
Simon Willison's Weblog
Simon Willison's Weblog
I
Intezer
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
T
Troy Hunt's Blog
Latest news
Latest news
Help Net Security
Help Net Security
S
Security Affairs
Webroot Blog
Webroot Blog
The Hacker News
The Hacker News
AI
AI
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
T
Tor Project blog
Forbes - Security
Forbes - Security
Google DeepMind News
Google DeepMind News
AWS News Blog
AWS News Blog
Attack and Defense Labs
Attack and Defense Labs
P
Proofpoint News Feed
www.infosecurity-magazine.com
www.infosecurity-magazine.com
H
Help Net Security
L
Lohrmann on Cybersecurity
S
SegmentFault 最新的问题
Google Online Security Blog
Google Online Security Blog
MongoDB | Blog
MongoDB | Blog
Cyberwarzone
Cyberwarzone
The Last Watchdog
The Last Watchdog
S
Securelist
N
News and Events Feed by Topic
S
Secure Thoughts
F
Fortinet All Blogs
博客园_首页
C
Cybersecurity and Infrastructure Security Agency CISA
量子位
M
MIT News - Artificial intelligence
F
Full Disclosure
T
The Blog of Author Tim Ferriss
T
Tailwind CSS Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Microsoft Security Blog
Microsoft Security Blog
I
InfoQ
P
Privacy International News Feed
L
LangChain Blog
Know Your Adversary
Know Your Adversary
C
CERT Recently Published Vulnerability Notes

CodeSky 代码之空

如何让 AI 成为 24 小时牛马:我的个人项目实践 - CodeSky 代码之空 AI 浪潮下真实诉求的想象空间—同志仍需努力 - CodeSky 代码之空 AI 浪潮下的新时代开发模式—AI Coding 的快速成长 - CodeSky 代码之空 体验豆包手机的 24 小时 - CodeSky 代码之空 Agent Platform Self-Host 开源项目对比 - Coze Studio - CodeSky 代码之空 Chrome 端到端网络排查战记 - CodeSky 代码之空 瞎逼逼:2025 年还没有升级研发工具的你落伍了吗 - CodeSky 代码之空 Project. 博客重建计划 - CodeSky 代码之空 群晖 Gitea + Gitea Actions 安装与部署服务教程 - CodeSky 代码之空 Python 音频去广告+字幕提取 - CodeSky 代码之空 群晖通过 Active Backup for Business 实现服务器快照 - CodeSky 代码之空 Windows WSL 启用 NVIDIA CUDA 配置教程 - CodeSky 代码之空 HTTP Auth From BasicAuth to WebAuthn - CodeSky 代码之空 Redis 分布式锁的实现 - CodeSky 代码之空 限流与常见实现 - CodeSky 代码之空 缓存:高并发读的救世主 - CodeSky 代码之空 如何解决服务中的事务问题 - CodeSky 代码之空 聊聊 MySQL 索引与索引设计 - CodeSky 代码之空 Redis 中使用键空间监听 key 过期消息 - CodeSky 代码之空 AI:Make 死宅 Great Again - CodeSky 代码之空
Redis 大 key、热 key 判别和解决方案 - CodeSky 代码之空
敖天羽 · 2024-09-20 · via CodeSky 代码之空

Redis 是我们常见的缓存解决方案,但是使用不当的 Redis 同样会造成系统瓶颈。

慢日志分析

要启用慢日志分析,首先先要对慢查询记录进行设置:

1# 命令执行耗时超过 5 毫秒,记录慢日志 
2CONFIG SET slowlog-log-slower-than 5000 
3# 只保留最近 500 条慢日志
4CONFIG SET slowlog-max-len 500
5

设置成功后通过下面的命令就能查到慢日志:

1127.0.0.1:6379> SLOWLOG get 5
21) 1) (integer) 32693 # 慢日志ID
3   2) (integer) 1593763337 # 执行时间戳
4   3) (integer) 5299 # 执行耗时(微秒)
5   4) 1) "LRANGE" # 具体执行的命令和参数
6      2) "user_list:2000"
7      3) "0"
8      4) "-1"
92) 1) (integer) 32692
10   2) (integer) 1593763337
11   3) (integer) 5044
12   4) 1) "GET"
13      2) "user_info:1000"
14

主要可能的原因无非也就是:

  1. 数据太大,导致网络 IO 耗时增加
  2. 命令复杂,导致 CPU 耗时增加

而要避免这种慢查询发生,就需要我们尽可能的避免复杂的查询和大 key 的产生。

而今天我们要说的重点就是关于 Redis 中的大 key 要怎么解决。

大 key

大 key 意味着 value 特别大(而不是 key 特别大),大 key 会导致的问题显而易见:

  1. 网络 IO:大 key 的读写都会导致网络 IO 的阻塞,形成上面所说的慢查询
  2. 内存倾斜:在 Redis cluster 中大 key 会存在某个节点,此时该节点会比其他节点消耗更多的内存和网络资源,形成卡点
  3. 阻塞查询:大 key 的读写和删除操作都在主线程中进行,会阻塞其他命令的执行,导致 redis 性能下降
  4. 影响持久化:持久化需要将数据写入磁盘,大 key 意味着单条日志写入量也会变大,持久化过程就会更耗时,甚至会频繁触发 AOF 重写。

因此如果没有特殊情况,我们要尽量避免大 key。

大 key 检测

要发现大 key 也很简单,可以直接通过下面的命令发现大 key:

1> redis-cli --bigkeys
2
3# Scanning the entire keyspace to find biggest keys as well as
4# average sizes per key type.  You can use -i 0.1 to sleep 0.1 sec
5# per 100 SCAN commands (not usually needed).
6
7100.00% ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
8Keys sampled: 18
9
10-------- summary -------
11
12Total key length in bytes is 155 (avg len 8.61)
13
14Biggest string found "rand_16_0" has 4 bytes
15Biggest   zset found "job:delayed" has 4 members
16
170 lists with 0 items (00.00% of keys, avg size 0.00)
180 hashs with 0 fields (00.00% of keys, avg size 0.00)
190 streams with 0 entries (00.00% of keys, avg size 0.00)
2017 strings with 67 bytes (94.44% of keys, avg size 3.94)
210 sets with 0 members (00.00% of keys, avg size 0.00)
221 zsets with 4 members (05.56% of keys, avg size 4.00)
23

当然,这种方法只能显示最大的那个 key,他不一定实际就是大 key,可能本身占用的内存并不多。

此外,如果在主节点执行,同样会阻塞运行,所以建议在从节点执行。

另外,也可以通过 SCAN来扫描 Redis,得到每个 key 的内存占用情况,从而感知到大 key 的存在:

1redis-cli --scan | while read key; do 
2  echo "$(redis-cli memory usage $key) $key"; 
3done | sort -nr | head
4

使用 SCAN 命令不会阻塞 Redis,比较安全。

但是缺点是效率较低,对大量 key 的 Redis 数据库扫描时间较长。

也可以使用一些第三方软件来完成这一动作,比如 Redis RDB Tools

删除大 key

实际上不仅读写会造成瓶颈,前面我们说过删除大 key 也会有性能问题。因为删除时不仅仅是删除一个操作,还会涉及到资源的回收和再分配,而 DEL是在主线程中执行的,Redis 中的执行命令是单线程的,这意味着直接影响了整个 Redis 的吞吐。

因此我们不能直接 DEL 大 key,更好的实践是使用 UNLINK代替 DEL,这样会分配另一个线程去回收,而不会阻塞主线程。

另一方面,如果 Redis 开启了 Lasy Free:lazyfree-lazy-user-del = yes,此时就不用 UNLINKDEL 也会由其他线程执行了,从而不阻塞主线程。

避免大 key

站在业务的角度,有时候可能不可避免的会产生一些大 key,但原则上我们依旧要尽可能的避免这种情况的出现。

拿我们上一篇缓存文章中微博的例子为例,如果一个微博大 V 有非常多的粉丝(假设有一千万),这些数据量即使我们只存储 user_id,也会有不小的数据。此时我们就可以将大 V 的粉丝拆分成多个子列表来进行查询,一个子列表放 5000 个粉丝 id,避免单 key 过大。

热 key

在上一篇文章中,我们也说过热 key 的问题,热 key 对 Redis 主要造成的影响是:

  1. 接口超时严重,逐步发生雪崩
  2. 网卡被打爆,大量请求失败
  3. 连接数被热 key 占据影响别的请求

说白了核心关键点就是网络实在不够用了。

而对于热 key 来说,除了加机器,还可以配合「发现-解决」的套路来减少热 key 带来的影响。

发现热 key

  1. 业务场景预估热 key:对于一些场景,我们可能能预估出爆点,比如某本季新番预订爆款,那八成就会变成热 key。但是不太能应对微博热搜这种突发场景。
  2. 客户端收集:在 Redis 调用的 SDK 中加入对命令的收集,来分析哪些 key 的访问最多,从而感知热 key。虽然方便,但是需要改造和引入 SDK,与业务耦合。
  3. 代理层收集:本质上和客户端没啥区别,只是从 SDK 变成了网络代理。从架构的角度上虽然与业务解耦了,多加了一层也容易造成单点风险。
  4. Redis 命令监控:
    1. monitor:用于实时打印出 Redis 服务器接收到的命令。但是在高并发的情况下容易拖累 redis 的性能,因此不太常用。
    2. hotkeys:redis-cli --hotkeys -i 0.1来获取,但是相当于全 key 扫描,key 较多时成本会比较高,而且全量扫描的耗时导致它的实时性较差。

解决热 key

对于热 key 来说,其实也没什么特别好的解决方案,主要也就是两个套路:

  1. 读写分离的情况下扩容
  2. 使用多级缓存

在发现热 key 的前提下构造多级缓存是一个比较正常的解决方案,这样有效降低了 Redis 的访问量,多级缓存的问题和解决方案在上一篇文章中也有提到。

总结

大 key 和 热 key 不仅仅是一个技术问题,同时也要站在业务的角度来选择一个合适的解决方案。