redis 突然大量逐出导致读写请求block
现象
redis作为缓存场景使用,内存耗尽时,突然出现大量的逐出,在这个逐出的过程中阻塞正常的读写请求,导致 redis 短时间不可用;
背景
redis 中的LRU是如何实现的?
- 当mem_used内存已经超过maxmemory的设定,对于所有的读写请求,都会触发redis.c/freeMemoryIfNeeded(void)函数以清理超出的内存。
- 这个清理过程是阻塞的,直到清理出足够的内存空间。
- 这里的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;
else
mem_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的更多相关文章
- redis作为缓存场景使用,内存耗尽时,突然出现大量的逐出,在这个逐出的过程中阻塞正常的读写请求,导致 redis 短时间不可用
redis 突然大量逐出导致读写请求block 内容目录: 现象 背景 原因 解决方案 ref 现象 redis作为缓存场景使用,内存耗尽时,突然出现大量的逐出,在这个逐出的过程中阻塞正常的读写请 ...
- Redis+MongoDB 最佳实践 做到读写分离 -摘自网络
方案1. (被否定) 加上Redis,做到MongoDB的读写分离,单一进程从MongoDB及时把任务同步到Redis中. 看起来很完美,但是上线后出现了各种各样的问题,列举一下: 1.Redis队列 ...
- 5.3 存储器、I/O和配置读写请求TLP
本节讲述PCIe总线定义的各类TLP,并详细介绍这些TLP的格式.在这些TLP中,有些格式对于初学者来说较难理解.读者需要建立PCIe总线中与TLP相关的一些基本概念,特别是存储器读写相关的报文格式. ...
- IE浏览器缓存导致Ajax请求失败
在IE浏览器中通过Ajax请求后台的数据,如果Page请求是postback类型的,可能会导致Ajax请求失败的问题 我们都知道ajax能提高页面载入的速度主要的原因是通过ajax减少了重复数据的载入 ...
- 解决ASP.NET中Redis 每小时6000次访问请求的问题
原文:解决ASP.NET中Redis 每小时6000次访问请求的问题 虽然ServiceStack v4是商业支持的产品,但我们也允许免费使用小型项目和评估目的.上面的NuGet包中包含可以使用许可证 ...
- redis快照关闭了导致不能持久化的问题
在使用redis的时候我们经常会遇到这种bug: Python与Redis交互时,设置数据出现下列报错信息: MISCONF Redis is configured to save RDB s ...
- Kafka技术内幕 读书笔记之(六) 存储层——服务端处理读写请求、分区与副本
如下图中分区到 日 志的虚线表示 : 业务逻辑层的一个分区对应物理存储层的一个日志 . 消息集到数据文件的虚线表示 : 客户端发送的消息集最终会写入日志分段对应的数据文件,存储到Kafka的消息代理节 ...
- IOS网络第二天 - 02-异步HTTP请求block回调 解析
************** #import "HMViewController.h" #import "MBProgressHUD+MJ.h" @interf ...
- asp.net session锁导致ajax请求阻塞
问:为了可以顺序访问Session的状态值,Session是否提供了锁定机制?答:Session实现了Reader/Writer的锁机制:当页面对Session具有可写功能(即页面有<%@Pag ...
随机推荐
- Docker for Web Developers目录
在OpenStack在私有云占主导定位之后,后起之秀Docker在PaaS平台.CI/CD.微服务领域展露锋芒.作为Web Developers,我们有必要学习和掌握这门技术. 1. 运行第一个Doc ...
- php与HTML交互问题
1.将表单中的action属性值设为PHP路径,则网页会跳转到这个网址 <html> <body> <form action="welcome.php" ...
- DNS服务器解析域名的过程
最近在读许令波老师的<深入分析Java Web技术内幕>,算是对DNS服务器域名解析有个大体的理解,以下的内容来自个人对书中内容的整理 1.什么是域名解析? 当我们在浏览器的地址栏输入一个 ...
- shell第一篇
前两天不停的再看内核相关的内容,了解内核的形成.内核的执行流程.内核的作用,结果是舍近求远. 其实我只是想了解一下shell的工作,shell与内核有关,但并不需要我么真正去做什么,至少对于我这样额初 ...
- ng机器学习视频笔记(十六) ——从图像处理谈机器学习项目流程
ng机器学习视频笔记(十六) --从图像处理谈机器学习项目流程 (转载请附上本文链接--linhxx) 一.概述 这里简单讨论图像处理的机器学习过程,主要讨论的是机器学习的项目流程.采用的业务示例是O ...
- records.config文件配置模板
# # # Process Records Config File # # <RECORD-TYPE> <NAME> <TYPE> <VALUE (till ...
- 计算机中RAM和ROM
1.RAM(RamdomAccessMemory): 易挥发性随机存取存储器,高速存取,读写时间相等,且与地址无关,如计算机内存等. 2.ROM(Read Only Memory): 只读存储器.断电 ...
- Core Animation 文档翻译 (第五篇)
构建Layer层次结构 在APP中大多数情况下,将Layer和View对象结合使用是Layer最好的使用方式.然而,很多时候我们可能需要通过添加单独的Layer对象,以便增加视图继承层次:当为了提 ...
- JAVA设计模式之---工厂模式
1.引言 工厂模式可以分为类: 1)简单工厂模式(Simple Factory) 2)工厂方法模式(Factory Method) 3)抽象工厂模式(Abstract Factory) 这种模式从上 ...
- mui页面跳转(传值+接收)
<script type="text/javascript" charset="utf-8"> mui.init(); mui.plusReady( ...