专栏首页DBA随笔Redis开发与运维学习笔记---(13)

Redis开发与运维学习笔记---(13)

//

Redis开发与运维学习笔记---(13)

//

如何高效利用Redis内存

我们知道redis的数据都保存在内存中,如何高效利用内存变得尤为重要。这里主要从内存消耗、管理内存的原理与方法、内存优化技巧三个方面来讲述如何高效实现内存的存储。今天仅描述内存消耗相关知识。

01

内存消耗

Redis的内存使用统计

redis中通过info memory命令获取内存相关的指标:

# Memory
used_memory:2043448
used_memory_human:1.95M
used_memory_rss:3198976
used_memory_peak:3089264
used_memory_peak_human:2.95M
used_memory_lua:36864
mem_fragmentation_ratio:1.57
mem_allocator:jemalloc-3.6.0

其中各个指标的含义如下:

used_memory:redis分配器分配的内存总量,也就是内部存储所有内存占用量;

used_memory_human:上述指标的易读模式

used_memory_rss:从操作系统角度显示的Redis进程占用的物理内存总量

used_memory_peak:内存使用的最大值,也就是峰值

used_memory_lua:Lua引擎所消耗的内存大小

mem_fragmentation_ratio:used_memory_rss/used_memory的比值,表示内存碎片率,如果该值大于1,说明多出的部分内存并没有用于存储,而是被内存碎片消耗,如果二者相差很大,则说明内存碎片率严重。如果该值小于1,这种情况一般出现在操作系统把Redis的内存交换到硬盘导致,这会导致Redis性能变得很差,需要格外注意。

mem_allocator:Redis所使用的内存分配器

redis的内存消耗,主要包含下面4个方面:

自身内存;

对象内存;

缓冲内存;

内存碎片;

其中redis空进程自身占用的内存消耗很少,通常used_memory_rss只有3MB左右,used_memory在800kb左右,空的Redis进程消耗的内存可以忽略不记。

对象内存是Redis内存占用最大的一块,它存储着用户的数据,Redis所有的数据都采用key-value存储,所有在使用的时候,要注意监控value对象的内存占用情况,避免内存溢出。

缓冲内存,这部分内存主要包括客户端缓冲,复制积压缓冲区,AOF缓冲区。

客户端缓冲是指所有接入到Redis服务器TCP链接的输入输出缓冲,输入缓冲无法控制,最大空间为1G,如果超过将断开连接。输出缓冲通过参数client-output-buffer-limit来控制。在主从环境中,主节点会为每个从节点单独建立一条连接用于命令复制,默认配置是:

client-output-buffer-limit slave 256mb 64mb 60

当主从节点之间的网络延迟较高,或者主节点挂载了大量从节点时,这部分内存消耗将占用很大一部分。输入输出缓冲区在大流量场景中容易失控。造成Redis内存不稳定,需要重点监控

复制积压缓冲区:该缓冲区默认1MB,所有的从节点共享主节点的复制积压缓冲区,该部分的内存设置可以适当调大点。

AOF缓冲区:这部分空间用于在Redis重写期间保存最近的写入命令。这部分空间占用通常很小

内存碎片:Redis默认采用jemalloc内存分配器,jemalloc分配内存的时候是按照内存块来分配的,如果要保存5kb的内容,可能会采用8kb的内存块来保存,剩余的3kb将变成内存碎片。jemalloc对内存碎片做了专门的优化,一般来讲mem_fragmentation_ratio在1.03左右,但是当存储数据长短差异较大时,下面场景容易出现内存碎片:

1、频繁做更新操作,例如频繁进行append,setrange等

2、大量过期键删除,过期删除后,释放的空间无法得到充分利用,导致碎片率上升

除此之外,还有子进程的内存消耗,子进程内存消耗主要是在AOF/RDB重写时Redis创建的子进程内存消耗。子进程带来的内存消耗总结如下:

1、Redis产生的子进程并不需要1倍的父进程内存,实际消耗根据期间写入命令量决定,但是依然要预留出一些内存防止溢出。

2、需要设置sysctl vm.overcommit_memory=1允许内核可以分配所有的物理内存,防止Redis进程执行fork时因内存剩余不足而失败。

02

内存管理

Redis的内存管理主要分为控制内存上限和回收策略。

首先来看控制内存上限的方法:

1、Redis使用maxmemory参数限制最大可用内存,限制内存的目的是防止内存超过服务器的物理内存。当超出maxmemory参数限制时,会使用LRU等删除策略释放空间。

2、我们可以通过config set maxmemory进行动态修改内存参数,当单机多实例上内存满载的时候,一个redis实例增加了maxmemory,另一个redis实例要对应减少maxmemory

除了内存上限的方法,回收策略也比较重要。常见的回收策略分为两种:

1、删除到达过期时间的键对象,可以通过redis自身的键过期时间或者定时任务巡检来进行删除。

2、内存使用达到maxmemory的时候,触发内存溢出的控制策略。

这里有必要说下redis的内存溢出控制策略,在redis中,支持6中策略:

a、noeviction:默认策略,不会删除任何数据,拒绝所有写入操作并返回给客户端OOM的错误信息;

b、volitile-lru:根据LRU算法删除设置了超市属性的键,知道腾出足够空间为止,如果没有可删除的对象,回退到上面的策略

c、allkeys-lru:根据LRU算法删除键,不管数据有没有设置超时属性,直到腾出足够空间为止

d、allkeys-random:随机删除所有键

e、volatile-random:随机删除过期键

f、volatile-ttl:根据键值对象的ttl属性删除最近将要过期的数据,如果没有,回退到a策略

该内存溢出控制策略可以通过config set maxmemory-policy {policy}动态配置。当redis由于内存溢出删除键时,可以通过info stats命令来查看evicted_keys指标找出当前redis服务器已经删除的键数量。

最后,有几点需要注意:

1、当redis一直工作在内存溢出的状态下,且设置为非noeviction策略时,会频繁地出发回收内存的操作,(频繁查找可删除键,频繁删除键),影响redis服务器的性能。

2、对于要收缩redis内存的场景,可以通过调小maxmemory来快速回收。但是在该过程中,可能会导致数据丢失和短暂的阻塞问题。

本文分享自微信公众号 - DBA随笔(gh_acc2bbc0d447),作者:AsiaYe

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-04-15

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Redis开发与运维学习笔记---(14)

    我们知道redis的数据都保存在内存中,如何高效利用内存变得尤为重要。这里主要从内存消耗、管理内存的原理与方法、内存优化技巧三个方面来讲述如何高效实现内存的存储...

    AsiaYe
  • Redis开发与运维学习笔记---(5)

    redis中的事务和MySQL中的事务类似,也是为了保证多条命令组合的原子性,为此,redis提供了简单的事务功能以及集成Lua来解决这个问题。下面我们来...

    AsiaYe
  • Redis运维之swap空间

    swap空间对于操作系统来说比较重要,当我们使用操作系统的时候,如果系统内存不足,常常会将一部分内存数据页进行swap操作,以解决临时的内存困境。swap...

    AsiaYe
  • 宝塔面板+云服务器内存经常爆满如何优化?

    很多低内存的服务器比如1G或者更低的服务器,安装宝塔面板后发现经常内存爆满,很多用户误以为是宝塔占用较大的内存导致的问题,其实不然,宝塔本身占用的系统内存并不高...

    wordpress建站吧
  • 内存虚拟化技术介绍之---内存去重

    前言 虚拟化的目的是为了提升硬件的资源利用率,包括CPU,内存、IO等。在各种虚拟化中,都有内存压缩、内存去重等技术。本文通过介绍PowerVM的内存去重技术,...

    魏新宇
  • Android内存优化(四)解析Memory Monitor、Allocation Tracker和Heap Dump

    前言 1.Memory Monitor 在Android Studio(以下简称AS)中Android Monitor是一个主窗口,它包含了Logcat,、Me...

    用户1269200
  • 笔记66 | eclipse/android studio/ADB查看Android应用内存使用情况

    项勇
  • 在 Python 中是如何管理内存的?

    Python内存池:内存池的概念就是预先在内存中申请一定数量的,大小相等 的内存块留作备用,当有新的内存需求时,就先从内存池中分配内存给这个需求,不够了之后再申...

    宇宙之一粟
  • C语言最大难点揭秘:编程的祸根!

    本文将带您了解一些良好的和内存相关的编码实践,以将内存错误保持在控制范围内。内存错误是 C 和 C++ 编程的祸根:它们很普遍,认识其严重性已有二十多年,但始终...

    公众号C语言与CPP编程
  • Zephyr 内存分配

    int k_mem_pool_alloc(struct k_mem_pool *p, struct k_mem_block *block, size_t si...

    无限之生

扫码关注云+社区

领取腾讯云代金券