Redis核心技术与实战
蒋德钧
中科院计算所副研究员
新⼈⾸单¥19.9
7813 人已学习
课程目录
已更新 24 讲 / 共 50 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词 | 这样学Redis,才能技高一筹
免费
基础篇 (10讲)
01 | 基本架构:一个键值数据库包含什么?
02 | 数据结构:快速的Redis有哪些慢操作?
03 | 高性能IO模型:为什么单线程Redis能那么快?
04 | AOF日志:宕机了,Redis如何避免数据丢失?
05 | 内存快照:宕机后,Redis如何实现快速恢复?
06 | 数据同步:主从库如何实现数据一致?
07 | 哨兵机制:主库挂了,如何不间断服务?
08 | 哨兵集群:哨兵挂了,主从库还能切换吗?
09 | 切片集群:数据增多了,是该加内存还是加实例?
10 | 第1~9讲课后思考题答案及常见问题答疑
实践篇 (10讲)
11 | “万金油”的String,为什么不好用了?
12 | 有一亿个keys要统计,应该用哪种集合?
13 | GEO是什么?还可以定义新的数据类型吗?
14 | 如何在Redis中保存时间序列数据?
15 | 消息队列的考验:Redis有哪些解决方案?
16 | 异步机制:如何避免单线程模型的阻塞?
17 | 为什么CPU结构也会影响Redis的性能?
18 | 波动的响应延迟:如何应对变慢的Redis?(上)
19 | 波动的响应延迟:如何应对变慢的Redis?(下)
20 | 删除数据后,为什么内存占用率还是很高?
加餐篇 (3讲)
加餐(一)| 经典的Redis学习资料有哪些?
加餐(二)| Kaito:我是如何学习Redis的?
加餐(三)| Kaito:我希望成为在压力中成长的人
Redis核心技术与实战
15
15
1.0x
00:00/00:00
登录|注册

19 | 波动的响应延迟:如何应对变慢的Redis?(下)

蒋德钧 2020-09-21
你好,我是蒋德钧。
上节课,我介绍了判断 Redis 变慢的两种方法,分别是响应延迟和基线性能。除此之外,我还给你分享了从 Redis 的自身命令操作层面排查和解决问题的两种方案。
但是,如果在排查时,你发现 Redis 没有执行大量的慢查询命令,也没有同时删除大量过期 keys,那么,我们是不是就束手无策了呢?
当然不是!我还有很多“锦囊妙计”,准备在这节课分享给你呢!
如果上节课的方法不管用,那就说明,你要关注影响性能的其他机制了,也就是文件系统和操作系统。
Redis 会持久化保存数据到磁盘,这个过程要依赖文件系统来完成,所以,文件系统将数据写回磁盘的机制,会直接影响到 Redis 持久化的效率。而且,在持久化的过程中,Redis 也还在接收其他请求,持久化的效率高低又会影响到 Redis 处理请求的性能。
另一方面,Redis 是内存数据库,内存操作非常频繁,所以,操作系统的内存机制会直接影响到 Redis 的处理效率。比如说,如果 Redis 的内存不够用了,操作系统会启动 swap 机制,这就会直接拖慢 Redis。
那么,接下来,我再从这两个层面,继续给你介绍,如何进一步解决 Redis 变慢的问题。

文件系统:AOF 模式

你可能会问,Redis 是个内存数据库,为什么它的性能还和文件系统有关呢?
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《Redis核心技术与实战》,如需阅读全部文章,
请订阅文章所属专栏新⼈⾸单¥19.9
立即订阅
登录 后留言

精选留言(13)

  • Kaito
    关于如何分析、排查、解决Redis变慢问题,我总结的checklist如下:

    1、使用复杂度过高的命令(例如SORT/SUION/ZUNIONSTORE/KEYS),或一次查询全量数据(例如LRANGE key 0 N,但N很大)

    分析:a) 查看slowlog是否存在这些命令 b) Redis进程CPU使用率是否飙升(聚合运算命令导致)

    解决:a) 不使用复杂度过高的命令,或用其他方式代替实现(放在客户端做) b) 数据尽量分批查询(LRANGE key 0 N,建议N<=100,查询全量数据建议使用HSCAN/SSCAN/ZSCAN)

    2、操作bigkey

    分析:a) slowlog出现很多SET/DELETE变慢命令(bigkey分配内存和释放内存变慢) b) 使用redis-cli -h $host -p $port --bigkeys扫描出很多bigkey

    解决:a) 优化业务,避免存储bigkey b) Redis 4.0+可开启lazy-free机制

    3、大量key集中过期

    分析:a) 业务使用EXPIREAT/PEXPIREAT命令 b) Redis info中的expired_keys指标短期突增

    解决:a) 优化业务,过期增加随机时间,把时间打散,减轻删除过期key的压力 b) 运维层面,监控expired_keys指标,有短期突增及时报警排查

    4、Redis内存达到maxmemory

    分析:a) 实例内存达到maxmemory,且写入量大,淘汰key压力变大 b) Redis info中的evicted_keys指标短期突增

    解决:a) 业务层面,根据情况调整淘汰策略(随机比LRU快) b) 运维层面,监控evicted_keys指标,有短期突增及时报警 c) 集群扩容,多个实例减轻淘汰key的压力

    5、大量短连接请求

    分析:Redis处理大量短连接请求,TCP三次握手和四次挥手也会增加耗时

    解决:使用长连接操作Redis

    6、生成RDB和AOF重写fork耗时严重

    分析:a) Redis变慢只发生在生成RDB和AOF重写期间 b) 实例占用内存越大,fork拷贝内存页表越久 c) Redis info中latest_fork_usec耗时变长

    解决:a) 实例尽量小 b) Redis尽量部署在物理机上 c) 优化备份策略(例如低峰期备份) d) 合理配置repl-backlog和slave client-output-buffer-limit,避免主从全量同步 e) 视情况考虑关闭AOF f) 监控latest_fork_usec耗时是否变长

    7、AOF使用awalys机制

    分析:磁盘IO负载变高

    解决:a) 使用everysec机制 b) 丢失数据不敏感的业务不开启AOF

    8、使用Swap

    分析:a) 所有请求全部开始变慢 b) slowlog大量慢日志 c) 查看Redis进程是否使用到了Swap

    解决:a) 增加机器内存 b) 集群扩容 c) Swap使用时监控报警

    9、进程绑定CPU不合理

    分析:a) Redis进程只绑定一个CPU逻辑核 b) NUMA架构下,网络中断处理程序和Redis进程没有绑定在同一个Socket下

    解决:a) Redis进程绑定多个CPU逻辑核 b) 网络中断处理程序和Redis进程绑定在同一个Socket下

    10、开启透明大页机制

    分析:生成RDB和AOF重写期间,主线程处理写请求耗时变长(拷贝内存副本耗时变长)

    解决:关闭透明大页机制

    11、网卡负载过高

    分析:a) TCP/IP层延迟变大,丢包重传变多 b) 是否存在流量过大的实例占满带宽

    解决:a) 机器网络资源监控,负载过高及时报警 b) 提前规划部署策略,访问量大的实例隔离部署

    总之,Redis的性能与CPU、内存、网络、磁盘都息息相关,任何一处发生问题,都会影响到Redis的性能。

    主要涉及到的包括业务使用层面和运维层面:业务人员需要了解Redis基本的运行原理,使用合理的命令、规避bigke问题和集中过期问题。运维层面需要DBA提前规划好部署策略,预留足够的资源,同时做好监控,这样当发生问题时,能够及时发现并尽快处理。
    2020-09-21
    4
    39
  • ꧁子华宝宝萌萌哒꧂

    echo never /sys/kernel/mm/transparent_hugepage/enabled
    这个是不是得改成
    echo never > /sys/kernel/mm/transparent_hugepage/enabled
    这样?
    2020-09-21
    1
    3
  • yeek
    如果redis是独立部署,那么当内存不足时,淘汰策略和操作系统的swap机制 哪个会优先执行?

    曾遇到过线上触发内存淘汰的场景,并未观察当时的swap情况,感谢老师的建议
    2020-09-21
    2
  • “8. 是否运行了 Redis 主从集群?如果是的话,把主库实例的数据量大小控制在 2~4GB,以免主从复制时,从库因加载大的 RDB 文件而阻塞。” 这个2~4G的经验值和主库的内存大小无关吗?比如主从库内存都是64G, 这个主库数据量依然是2~4G?
    2020-09-21
    1
    1
  • 小喵喵
    有时候需要内存大页怎么办?如何判断是否需要启用内存大页机制呢?
    2020-09-24
  • 小喵喵
    请问下老师什么样的key叫bigkey呢?
    2020-09-24
  • 王世艺
    看了下,貌似是这样
    redis 有一个aof_buf缓存,用来缓存新的aof操作信息。
    正常情况下主线程每次循环都是先将aof_buff write,然后aof_buf是清空,
    主线程会用去fsync,已经write的内容。
    刷盘当时aways的情况下,主线程去直接调用redis_fsync。
    但是当策略是EVERYSEC时,主线程会用aof_background_fsync中的bioCreateBackgroundJob(BIO_AOF_FSYNC,(void*)(long)fd,NULL,NULL);创建子线程去完成。

    但是当io压力大的时候,也就是aof_buf有积压是。主线程在EVERYSEC模式下回去判断。是否有aofwrite在执行,并超过2s
    如果超过2s主线程不会return,继续将aof_buf write
    代码:nwritten = aofWrite(server.aof_fd,server.aof_buf,sdslen(server.aof_buf));
    但是因为子线程在aof_fd上fsync,所以write aof_fd的请求会被堵塞,这里write全是主线程在操作,堵塞直到fsync完成,能改变文件描述符(aof_fd),主线程才可以继续响应请求
    2020-09-23
  • Sunny
    set/list 类型算bigkey 吗? 考虑到主从库同步的时候,操作这个类型很耗时,求证下。
    2020-09-22
  • 王世艺
    当主线程使用后台子线程执行了一次 fsync,需要再次把新接收的操作记录写回磁盘时,如果主线程发现上一次的 fsync 还没有执行完,那么它就会阻塞

    老师这段代码逻辑在哪里
    2020-09-22
  • 云学
    除了绑定cpu也可以提升redis进程静态优先级,得到更多cpu调度
    2020-09-21
  • 土豆白菜
    老师会讲布隆过滤器吗?
    2020-09-21
  • tt
    可以再仔细分析一下,在虚拟机上部署REDIS实例时,由于虚拟化软件本身的内存管理算法导致的SWAP分析过程和在物理机上部署时的不同么?
    2020-09-21
  • yeek
    当主线程使用后台子线程执行了一次 fsync,需要再次把新接收的操作记录写回磁盘时,如果主线程发现上一次的 fsync 还没有执行完,那么它就会阻塞。所以,如果后台子线程执行的 fsync 频繁阻塞的话(比如 AOF 重写占用了大量的磁盘 IO 带宽),主线程也会阻塞,导致 Redis 性能变慢。


    这段没懂,redis主线程和后台子线程之间有状态通信吗?主线程调用fsync对子线程而言是任务队列的方式还是同步调用的方式? 我去看看源码吧……
    2020-09-21
收起评论
13
返回
顶部