现象

redis作为缓存场景使用,内存耗尽时,突然出现大量的逐出,在这个逐出的过程中阻塞正常的读写请求,导致 redis 短时间不可用;

背景

redis 中的LRU是如何实现的?

  1. 当mem_used内存已经超过maxmemory的设定,对于所有的读写请求,都会触发redis.c/freeMemoryIfNeeded(void)函数以清理超出的内存。
  2. 这个清理过程是阻塞的,直到清理出足够的内存空间。
  3. 这里的LRU或TTL策略并不是针对redis的所有key,而是以配置文件中的maxmemory-samples个key作为样本池进行抽样清理。
    maxmemory-samples在redis-3.0.0中的默认配置为5,如果增加,会提高LRU或TTL的精准度,redis作者测试的结果是当这个配置为10时已经非常接近全量LRU的精准度.

原因

逐出qps突增非常大的原因:一次需要逐出释放太多的空间会导致阻塞;具体的原因是 mem_tofree 的计算逻辑有问题;
mem_tofree 统计的是:实际已分配的内存总量 - AOF 缓冲区相关的内存;
如果这时候有rehash,会临时分配一个桶来做rehash,这部分内存未排除,所以在rehash阶段,算出来的mem_tofree 就会很大,造成一个时刻需要逐出大量的key,逐出的loop是阻塞的,这个阶段会block redis的请求;

逐出qps的计算:

freeMemoryIfNeeded(...)// 计算出 Redis 目前占用的内存总数,但有两个方面的内存不会计算在内:// 1)从服务器的输出缓冲区的内存// 2)AOF 缓冲区的内存// 3)AOF 重写缓冲区中的内存mem_used = zmalloc_used_memory();if (slaves) {listIter li;listNode *ln;listRewind(server.slaves,&li);while((ln = listNext(&li))) {redisClient *slave = listNodeValue(ln);unsigned long obuf_bytes = getClientOutputBufferMemoryUsage(slave);if (obuf_bytes > mem_used)mem_used = 0;elsemem_used -= obuf_bytes;}}if (server.aof_state != REDIS_AOF_OFF) {mem_used -= sdslen(server.aof_buf);mem_used -= aofRewriteBufferSize();}// 计算需要释放多少字节的内存mem_tofree = mem_used - server.maxmemory;propagateExpire(db,keyobj);// 计算删除键所释放的内存数量delta = (long long) zmalloc_used_memory();dbDelete(db,keyobj);delta -= (long long) zmalloc_used_memory();mem_freed += delta;// 对淘汰键的计数器增一server.stat_evictedkeys++;

解决方案

github上 @Rosanta 给出的解决方案:释放内存的循环逻辑中最多执行一定次数,达到阈值了就不再逐出,到下个请求来时再释放一点空间;这个方案的好处是不会 block 整个进程,正常的业务读写请求无影响;潜在问题是可能单次写入的数据比释放的空间还大,导致总的内存是一直上升,而不是下降;

@antirez 给的方案:同样是迭代删除,但会加个标志,保证在迭代删除的逻辑下内存是逐渐下降的,而如果是上升的,还是会block住正常的请求(要控制主总的内存大小);
详见:
https://github.com/antirez/redis/pull/4583

ref

关于 redis 4.0的逐出算法优化
http://antirez.com/news/109

redis 突然大量逐出导致读写请求block相关推荐

  1. redis数据库无法写入导致的bug

    昨天发现运行得好好的系统出现bug了,最后检查发现redis无法修改数据导致的,在追查了一下,内存使用量超过maxmemory设置了,于是把maxmemory调大就ok了

  2. 读写分离oracle redis,redis集群主从之读写分离

    redis集群主从之读写分离 1.集群部署 这里就不详细赘述如何部署主从集群了,一般都是使用slaveOf配置来进行初始化配置. 2.与springboot集成实现读写分离 通过注解实现调用层读写分离 ...

  3. redis快照关闭了导致不能持久化的问题

    在使用redis的时候我们经常会遇到这种bug: Python与Redis交互时,设置数据出现下列报错信息: MISCONF Redis is configured to save RDB snaps ...

  4. pcie读写ddr_5.3 存储器、I/O和配置读写请求TLP

    本节讲述PCIe总线定义的各类TLP,并详细介绍这些TLP的格式.在这些TLP中,有些格式对于初学者来说较难理解.读者需要建立PCIe总线中与TLP相关的一些基本概念,特别是存储器读写相关的报文格式. ...

  5. Redis从库失败导致集群概率读不到

    ​目录 故障描述 处理经过 原因分析 故障总结 新入职的小O同学正在吃饭,突然 故障描述 Redis无法正常提供数据,研发请求Redis一会能读到数据一会读不到数据 处理经过 时间 处理同学 动作 1 ...

  6. ajax浏览器操作发生异常,解决IE浏览器缓存导致AJAX请求数据异常

    IE10浏览器会把AJAX请求的数据都缓存下来,然后每次想去刷新数据时发现数据都是一样的,于是导致数据显示异常. 解决方法: 在页面 标签里,加上以下声明: 保存后,刷新页面,重新访问即可. 说明:最 ...

  7. 深度解析串行并发并行,开发人员需彻底搞懂丨mysql|redis|skynet|协程|索引|读写分离|分布式锁|主从同步

    深度解析串行并发并行,开发人员需彻底搞懂 视频讲解如下,点击观看: 深度解析串行并发并行,开发人员需彻底搞懂丨mysql|redis|skynet|协程|索引|读写分离|分布式锁|主从同步丨C/C++ ...

  8. 表格滚动分页加载——使用element-plus的无限滚动v-infinite-scroll与el-table同时使用出现滚动条定位到底部导致一直请求接口

    不知道UI抽什么风,所有列表都没用分页器,一律采用滚动加载.但我又是个懒蛋,不想手写所以就用了element-plus的无限滚动,但是v-infinite-scroll和el-table这俩搁一块就有 ...

  9. 部署Redis作为mysql缓存实现读写分离

    1. redis+mysql缓存服务器实现读写分离 Redis其实就是说把表中经常访问的记录放在了Redis中,然后用户查询时先去查询Redis再去查询MySQL,确实实现了读写分离,也就是Redis ...

最新文章

  1. php 判断是否gzip,PHP网站判断页面文件或图片是否经过gzip压缩
  2. C语言-------基础知识小结(1)。
  3. IDEA连接Mysql报错: 未找到驱动程序类 ‘com.mysql.cj.jdbc.Driver‘.  Change driver class
  4. Zoom惊人财报、传苹果打造搜索引擎与谷歌竞争、Netflix部分剧集免费以吸引新用户等| Decode the Week...
  5. 如何为SAP API Portal上创建的API增添API key验证保护功能
  6. J - 青蛙的约会(扩展欧几里得)
  7. 成功人士都有的好习惯
  8. 使用spring的@autowired注解,无法实例化dao
  9. python远程调用摄像头_Python设置Socket代理及实现远程摄像头控制的例子
  10. python给函数添加属性_如何在python中自动向类添加属性?
  11. linux中pss用法,[Linux] Memory: VSS/RSS/PSS/USS
  12. TortoiseSVN搭建本地版本库及简单操作使用
  13. Linq 入门系列 [Take,Skip,TakeWhile,SkipWhile]篇
  14. 去除wmv等视频认证的方法
  15. 【云大会】之五《第七届云计算大会 Day1感受:喧嚣退潮、人气萎缩》
  16. 计算机局域网访问受限制,电脑本地连接受限制的处理方法
  17. 主窗口(10):【类】QWidgetAction [官翻]
  18. 学习B站UP雨落弦鸣的《超简单效果超好的个人网站博客搭建(对小白很友好)》中遇到的问题
  19. 解决Redis manger 连接不上linux redis的问题
  20. 字模的原理和获取(一)

热门文章

  1. python3 image模块_python3之成像库pillow
  2. 企业信息管理平台_OAJava企业信息化系统
  3. python用户名密码登录、错误三次结束_Python实现简单的用户登录信息确认,密码输错3次后,用户被锁定...
  4. auve子表单中只读不好用
  5. php判断版本根据版本调用不同,C#_C#自动判断Excel版本使用不同的连接字符串,用OLEDB通过设置连接字符串可 - phpStudy...
  6. 计算机话筒接口,电脑麦克风插口是哪个哪位知道?
  7. python命令解析_python解析命令行
  8. pythonpass函数_有的python内置函数怎么就一个pass?
  9. python书籍_python书籍购买建议
  10. 土地利用转移矩阵图怎么做_土地利用转移矩阵生成的几种方法