|

分类

redis 

|

遇到一个redis实例突然内存飙高的案例, 具体症状如下:

  • 客户端使用异步访问模式
  • 单个请求的回包很大,hgetall一个8M的key

由于访问量比较大,已经登录不上redis了, 看不到具体在做什么做操, 因此使用perf来看下调用栈, 此处且按下不表。

为何内存会飙高呢,我们线下重现一下:

import redis
import time r=redis.Redis("127.0.0.1", 9988)
pipe = r.pipeline()
key="8Mhashkey"
for i in range(100):
pipe.hgetall(key)
rsp=pipe.execute()
time.sleep(1)

执行这个脚本若干次, 我们可以发现9988的内存瞬间升高了, 而9988本身只有一个key, 8Mhashkey。

执行一下client list, 得到:

可以发现,是client 的output buffer占用的大量的内存。 那为什么会出现这个现象呢? 根本原因是: redis并不是使用ping/pong的模式来处理请求。对于来自同一个连接上面的请求,并不是走如下模式:

大专栏  一个异步访问redis的内存问题anguage-css highlighter-rouge">
1. 接受客户端请求
2. 处理请求,生成回包
3. 给客户端发送回包,跳转1

而是这种模式:

// 处理请求
1. 接受客户端请求
2. 处理请求生成回包, 跳转1 // 处理回复
while 有回包
把回包发给客户端

也就是说, 也就是说对于同一个连接上的请求,不需要等上一个请求的回包都被发送到客户端了,才去处理下一个请求; 即使上一个请求的回包没有被发送到客户端, redis也可以去接受并处理下一个请求。 redis把这些请求的回包都保存在内存里面了,内存大小通过如下参数配置:

client-output-buffer-limit normal 0 0 0

epoll_wait在返回时, 如果客户端连接可写,则向这些客户端上面上送回包, 已经发送给客户端的回包所对应的内存会被释放。

到此, 原因就明显了。 异步方式访问redis时,如果生成回包的速度大于客户端读取回包的速度,redis的内存就会上涨。

突然想起来上次在SACC上面有人问我异步访问redis有什么问题,当时由于时间关系没有解释很充分。 现在看来,redis的这种网络模型,收包和回包互不阻塞的方式,在多链接的情况下,不同链接上的请求上的延时是能保证的。 唯一的问题,可能就是这个内存问题。

上一篇
   
下一篇

一个异步访问redis的内存问题的更多相关文章

  1. 2020-05-11:redis 10G 内存开一个实例 和redis 1G内存开10个实例有什么区别

    福哥答案2020-05-11: 此答案不完善,仅供参考.开10个实例相对更占资源,在多核下能充分利用资源.

  2. Springboot2.0访问Redis集群

    Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作高性能的key-value数据库.缓存和消息中间件,掌握它是程序员的必备技能,下面是一个springboot访问redis的 ...

  3. 180626-Spring之借助Redis设计一个简单访问计数器

    文章链接:https://liuyueyi.github.io/hexblog/2018/06/26/180626-Spring之借助Redis设计一个简单访问计数器/ Spring之借助Redis设 ...

  4. Redis学习-内存优化

    以下为个人学习Redis的备忘录--内存优化 1.随时查看info memory,了解内存使用状况:127.0.0.1:6379> info memory# Memoryused_memory: ...

  5. python访问redis

    python访问redis 1 Linux上安装redis a) 下载 $ wget http://download.redis.io/releases/redis-3.0.5.tar.gz b) 编 ...

  6. Redis系列--内存淘汰机制(含单机版内存优化建议)

    https://blog.csdn.net/Jack__Frost/article/details/72478400?locationNum=13&fps=1 每台redis的服务器的内存都是 ...

  7. C语言使用hiredis访问redis

    Hiredis 是Redis数据库的简约C客户端库.它是简约的,因为它只是增加了对协议的最小支持,但是同时它使用了一个高级别的 printf-like API,所以对于习惯了 printf 风格的C编 ...

  8. 深入了解一下Redis的内存模型!

    一.前言 Redis是目前最火爆的内存数据库之一,通过在内存中读写数据,大大提高了读写速度,可以说Redis是实现网站高并发不可或缺的一部分. 我们使用Redis时,会接触Redis的5种对象类型(字 ...

  9. redis六种内存淘汰策略学习

    当客户端会发起需要更多内存的申请,Redis检查内存使用情况,如果实际使用内存已经超出maxmemory,Redis就会根据用户配置的淘汰策略选出无用的key; 当前Redis3.0版本支持的淘汰策略 ...

随机推荐

  1. Java文字识别软件-调用百度ocr实现文字识别

    java_baidu_ocr Java调用百度OCR文字识别API实现图片文字识别软件 这是一款小巧方便,强大的文字识别软件,由Java编写,配上了窗口界面 调用了百度ocr文字识别API 识别精度高 ...

  2. MySQL导入sql文件,过大导致错误

    --导入sql脚本文件,报错: Navicat 导入数据报错 --- 1153 - Got a packet bigger than 'max_allowed_packet' bytes2006 - ...

  3. vue路由的跳转-路由传参-cookies插件-axios插件-跨域问题-element-ui插件

    ---恢复内容开始--- 项目初始化 创建一个纯净的vue环境项目,手动书写全局的样式配置,全局的main,js配置 (1)如果vue项目在重构或者出错的时候,手动安装node_modules. 如果 ...

  4. linux下nfs共享目录

    1. 关掉防火墙    systemctl disable firewalld.service 2. 关掉selinux    vim /etc/selinux/config    修改第七行:    ...

  5. Django+ajax 返回json数据挨个显示在页面及页面和后台相互传值

    通过Ajax传到后台一个值,根据该值返回数据库表中的某一列的值,然后逐个显示到页面,并且给每个加上超链接,可以进行点击查看详细信息 1.通过Ajax传到后台一个值,红色部分为往Django后台传值,蓝 ...

  6. iTOP4412开发板-使用buildroot搭建最简单的linux

    本文档介绍的是使用buildroot搭建最简单的linux文件系统,Buildroot是Linux平台上一个构建嵌入式Linux系统的框架.整个Buildroot是由Makefile脚本和Kconfi ...

  7. 三十八、LNMP潮流组合搭建

    一.安装mysql 数据库 1.1  mysql数据库安装的三种方法: 1)编译安装,在lamp经典组合安装是5.1版本,是configure,make,make install,这里如果是5.5版本 ...

  8. 401认证钓鱼demo

    <?php //@b4dboy if(!isset($_SERVER['PHP_AUTH_USER']) && !isset($_SERVER['PHP_AUTH_PW'])) ...

  9. Nginx的下载与安装

    .创建文件输入网页中需要复制的 cat >/etc/yum.repos.d/nginx.repo<<EOF [nginx-stable] name=nginx stable repo ...

  10. VS制作dll、def文件的使用、dll加入工程使用

    1.VS新建工程,在选项的时候,选择dll和空项目,保持干净的dll库: 创建完以后,添加头文件以及源文件. 2.将外部模块使用的接口导出: (1)函数导出: __declspec(dllexport ...