一个异步访问redis的内存问题


|

分类

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的这种网络模型,收包和回包互不阻塞的方式,在多链接的情况下,不同链接上的请求上的延时是能保证的。 唯一的问题,可能就是这个内存问题。

上一篇
???
下一篇

原文地址:https://www.cnblogs.com/lijianming180/p/12247634.html

时间: 2024-08-27 17:43:37

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

使用C++ boost从零构建一个异步文件IO系统

前言 因为本科毕业设计中要做一个分布式文件系统,其中一个模块需要实现文件IO.为了验证我对异步IO的理解,决定造一个异步文件IO的轮子.操作系统已经给出各种异步操作的API,如重叠IO, IOCP,kqueue,select,poll,epoll等机制,而且C++也有很多跨平台的异步IO库,如libevent,boost::asio等.我参考已有的实现来完善这个小系统的功能. 渣技术,渣代码,出现问题请各位指出. 概述 同步与异步: 同步:假如我想对一个文件(socket也同理)进行处理,那么一

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

跳跃表是一种有序数据结构,通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的.除了跳跃表,实现有序数据结构的另一种典型实现是平衡树:大多数情况下,跳跃表的效率可以和平衡树媲美,且跳跃表实现比平衡树简单很多,因此redis中选用跳跃表代替平衡树.跳跃表支持平均O(logN).最坏O(N)的复杂点进行节点查找,并支持顺序操作.Redis的跳跃表实现由zskiplist和zskiplistNode两个结构组成:前者用于保存跳跃表信息(如头结点.尾节点.长度等),后者用于表示跳跃表节

C语言使用hiredis访问redis

Hiredis 是Redis数据库的简约C客户端库.它是简约的,因为它只是增加了对协议的最小支持,但是同时它使用了一个高级别的 printf-like API,所以对于习惯了 printf 风格的C编程用户来说,其非常容易使用,而且API中没有明确的绑定每个 Redis 命令. Github: https://github.com/redis/hiredis 安装hiredis 编译安装: $ git clone [email protected]:redis/hiredis.git $ cd

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

https://blog.csdn.net/Jack__Frost/article/details/72478400?locationNum=13&fps=1 每台redis的服务器的内存都是有限的,而且也不是所有的内存都用来存储信息.而且redis的实现并没有在内存这块做太多的优化,所以实现者为了防止内存过于饱和,采取了一些措施来管控内存. 文章结构:(1)内存策略:(2)内存释放机制原理:(3)项目中如何合理应用淘汰策略:(4)单机版Redis内存优化注意点. 一.内存策略:先来吃份官方文档

Redis的内存淘汰

Redis占用内存大小 我们知道Redis是基于内存的key-value数据库,因为系统的内存大小有限,所以我们在使用Redis的时候可以配置Redis能使用的最大的内存大小. 1.通过配置文件配置 通过在Redis安装目录下面的redis.conf配置文件中添加以下配置设置内存大小 //设置Redis最大占用内存大小为100Mmaxmemory 100mb redis的配置文件不一定使用的是安装目录下面的redis.conf文件,启动redis服务的时候是可以传一个参数指定redis的配置文件

Redis 系列(04-2)Redis原理 - 内存回收

目录 Redis 系列(04-2)Redis原理 - 内存回收 Redis 系列目录 1. 过期策略 1.1 定时过期(主动淘汰) 1.2 惰性过期(被动淘汰) 1.3 定期过期 2. 淘汰策略 2.1 最大内存设置 2.2 淘汰策略 2.4 LFU Redis 系列(04-2)Redis原理 - 内存回收 Redis 系列目录 相关文档推荐: Redis - LRU Reids 所有的数据都是存储在内存中的,在某些情况下需要对占用的内存空间进行回收.内存回收主要分为两类,一类是 key 过期,

面试官:Redis 数据库内存数据满了,会宕机吗?有内存回收?

Redis 数据库内存数据满了,会宕机吗?答案是:不会让他出现存满的情况,在使用Redis的时候我们要配置Redis能使用的最大的内存大小,存到一定容量的时候还有Redis的内存淘汰策略呢,还有LRU算法进行淘汰,等等...接下来就跟着作者一起探讨,Redis的内存淘汰策略. Redis占用内存大小 我们知道Redis是基于内存的key-value数据库,因为系统的内存大小有限,所以我们在使用Redis的时候可以配置Redis能使用的最大的内存大小. 1.通过配置文件配置 通过在Redis安装目

使用ab.exe监测100个并发/100次请求情况下同步/异步访问数据库的性能差异

ab.exe介绍 ab.exe是apache server的一个组件,用于监测并发请求,并显示监测数据 具体使用及下载地址请参考:http://www.cnblogs.com/gossip/p/4398784.html 本文的目的 通过webapi接口模拟100个并发请求下,同步和异步访问数据库的性能差异 创建数据库及数据 --创建表结构 CREATE TABLE dbo.[Cars] ( Id INT IDENTITY(1000,1) NOT NULL, Model NVARCHAR(50) 

ASP.NET MVC中使用ASP.NET AJAX异步访问WebService

使用过ASP.NET AJAX的朋友都知道,怎么通过ASP.NET AJAX在客户端访问WebService,其实在ASP.NET MVC中使用ASP.NET AJAX异步访问WebService 也没什么大的差别. 在ASP.NET应用程序里使用ASP.NET AJAX访问WebService通常都是通过ScriptMananger引入WebService生成客户端代理的方法,同时也可以使用Microsoft Ajax Library来完成.本文将介绍在ASP.NET MVC中使用ASP.NE