NotSQL 之 Redis(四)(性能管理之内存优化篇)


前言

  • Redis 是基于内存的 key-value 数据库,内存的大小是有限制的
  • 在生产环境中,偶尔会遇到 Redis 服务器内存不够的情况,那对于这种情况 Redis 的内存是如何回收处理的呢?如果内存满了,Redis 会怎么办呢

一、查看 Redis 内存使用

#使用 192.168.126.15:6379 连接本机上的 Redis 数据库
[root@localhost ~]# redis-cli -h 192.168.126.15 -p 6379
192.168.126.15:6379> INFO memory    #查看内存使用情况
# Memory
used_memory:853728                  #由 Redis 分配器分配的内存总量,包含了 redis 进程内部的开销和数据占用的内存,以字节(byte)为单位
used_memory_human:833.72K           #已更直观的单位展示分配的内存总量
used_memory_rss:16302080            #向操作系统申请的内存大小,与 top  ps 等命令的输出一致
used_memory_rss_human:15.55M        #已更直观的单位展示向操作系统申请的内存大小
used_memory_peak:853728             #redis 的内存消耗峰值(以字节为单位)
used_memory_peak_human:833.72K      #以更直观的格式返回 redis 的内存消耗峰值
used_memory_peak_perc:100.00%       #使用内存达到峰值内存的百分比,即(used_memory / used_memory_peak) *100%
used_memory_overhead:841390         #Redis 为了维护数据集的内部机制所需的内存开销,包括所有客户端输出缓冲区、查询缓冲区、AOF 重写缓冲区和主从复制的 backlog
used_memory_startup:791416          #Redis 服务器启动时消耗的内存
used_memory_dataset:12338           #数据占用的内存大小,即 used_memory - sed_memory_overhead
used_memory_dataset_perc:19.80%     #数据占用的内存大小的百分比,100%*(used_memory_dataset/(used_memory - used_memory_startup))
allocator_allocated:1304352
allocator_active:1634304
allocator_resident:11395072
total_system_memory:3958075392      #整个系统内存
total_system_memory_human:3.69G     #以更直观的格式显示整个系统内存
used_memory_lua:37888               #Lua 脚本存储占用的内存
used_memory_lua_human:37.00K        #以更直观的格式显示 Lua 脚本存储占用的内存
used_memory_scripts:0
used_memory_scripts_human:0B
number_of_cached_scripts:0
maxmemory:0                         #Redis 实例的最大内存配置
maxmemory_human:0B                  #以更直观的格式显示 Redis 实例的最大内存配置
maxmemory_policy:noeviction         #当达到 maxmemory 时的淘汰策略
allocator_frag_ratio:1.25
allocator_frag_bytes:329952
allocator_rss_ratio:6.97
allocator_rss_bytes:9760768
rss_overhead_ratio:1.43
rss_overhead_bytes:4907008
mem_fragmentation_ratio:20.06       #碎片率,used_memory_rss/ used_memory,>1表示有碎片,<1表示部分Redis的内存被系统交换到硬盘(此时Redis性能变差)
mem_fragmentation_bytes:15489376
mem_not_counted_for_evict:96
mem_replication_backlog:0
mem_clients_slaves:0
mem_clients_normal:49694
mem_aof_buffer:96
mem_allocator:jemalloc-5.1.0        #内存分配器
active_defrag_running:0             #表示没有活动的 defrag 任务正在运行,1 表示有活动的 defrag 任务正在运行(defrag:表示内存碎片整理)
lazyfree_pending_objects:0          #0表示不存在延迟释放的挂起对象

二、内存碎片率的计算

  • 由操作系统分配的内存值 used_memory_rss 除以 Redis 使用的内存值 used_memory 计算得出
    mark
used_memory_rss:是Redis向操作系统申请的内存
used_memory:是Redis中的数据占用的内存
mem_fragmentation_ratio:内存碎片率

mem_fragmentation_ratio = used_memory_rss / used_memory

三、内存碎片的产生

内存碎片是由操作系统低效的分配/回收物理内存导致的(不连续的物理内存分配):

  • Redis 内部有自己的内存管理器,为了提高内存使用的效率,来对内存的申请和释放进行管理
  • Redis 中的值删除的时候,并没有把内存直接释放,交还给操作系统,而是交给了 Redis 内部有内存管理器
  • Redis 中申请内存的时候,也是先看自己的内存管理器中是否有足够的内存可用
  • Redis 的这种机制,提高了内存的使用率,但是会使 Redis 中有部分自己没在用,却不释放的内存,导致了内存碎片的发生

三、内存碎片率的意义

跟踪内存碎片率对理解 Redis 实例的资源性能是非常重要的:

  • 内存碎片率稍大于 1 是合理的,这个值表示内存碎片率比较低
  • 内存碎片率超过 1.5,说明 Redis 消耗了实际需要物理内存的 150%,其中 50% 是内存碎片率,需要考虑是否要进行内存碎片清理,要引起重视
  • 内存碎片率低于 1 的,说明 Redis 内存分配超出了物理内存,则操作系统正在进行内存交换,也就是说,开始使用硬盘了;需要增加可用物理内存(扩容内存)或减少 Redis 的内存占用

四、如何解决内存碎片率过大的现象

1.低于 4.0版本的 Redis

shutdown save
#在redis-cli 工具上输入,随后重启 Redis 服务器
#Redis 服务器重启后,Redis 会将没用的内存归还给操作系统,碎片率会降下来

2.高于 4.0版本的 Redis

#Redis 4.0版本开始,可以在不重启的情况下,线上整理内存碎片

CONFIG SET activedefrag yes
#内存自动清理

memory purge
#手动直接清理
INFO memory
#再次查看

五、内存使用率

  • Redis 实例的内存使用率超过可用最大内存,操作系统就将开始进行内存与 swap 空间交换
  • 避免内存交换发生的方法:
    • 针对缓存数据大小选择安装 Redis 实例(对于每一个 key,将使用更少的内存,即指针占用的字节数更少)
    • 尽可能的使用 Hash 数据结构存储(Redis 在存储小于 100 个字段的 Hash 结构上,其存储效率非常高)
    • 设置 key 的过期时间(减少 key 的数量)

六、内回收 key(内存驱逐策略)

  • 保证合理分配 redis 有限的内存资源
  • 当达到配置文件最大内存限制的时候,需选择一种 key 的回收策略,即 Redis 有几种策略来处理这种情况:默认情况下回收策略是禁止删除
  • 在配置文件中修改 maxmemory-policy 属性值(直接修改对应部分即可):
vim /etc/redis/6379.conf
#598
maxmemory-policy noeviction
#noenviction(默认策略):禁止淘汰数据,对于写请求不再提供服务,直接返回错误(DEL请求和部分特殊请求除外)
#volatile-lru:从设置了过期时间的 key 中使用 LRU 算法进行淘汰
#volatile-ttl:在设置了过期时间的 key中,根据 key 的过期时间进行淘汰,越早过期的越优先被淘汰
#volatile-random:从设置了过期时间的 key 中随机淘汰
#allkeys-lru:从所有 key 中使用 LRU 算法进行淘汰
#allkeys-random:从数据集合中任意选择数据淘汰
  • 驱逐策略如何生效:
    • 当 Redis 收到一条会添加数据的命令
    • Redis 检查内存使用情况,是否超过最大内存限制
    • 超过则执行内存驱逐策略,然后执行命令

tips:如果某个命令大量使用内存,则占用内存可能会超过最大内存限制

猜你喜欢

转载自blog.csdn.net/weixin_51486343/article/details/114022048