09-Redis内存优化

nobility 发布于 2022-11-07 2690 次阅读


Redis内存优化

内存统计

使用info memory命令可以查看到以下参数

参数 描述
used_memory Redis分配器分配的内存量,也就是实际存储数据的内存总量
used_momory_human 以人可读格式返回Redis使用的内存总量
used_momory_rss 从操作系统的角度,Redis进程占用的总物理内存
used_memory_peak 内存分配器分配的最大内存,代表used_memory的历史峰值
used_memory_peak_human 以人可读的格式显示内存消耗峰值
used_memory_lua Lua引擎所消耗的内存
mem_fragmentation_ratio used_memory_rss/used_memory比值,表示内存碎片率
mem_allocator Redis所使用的内存分配器,默认:jemalloc

内存消耗划分

内存优化

客户端缓冲区

配置
  • 输出缓冲区:就是命令的返回结果,每个客户端都是不同的,可通过client-output-buffer-limit配置项进行配置(若这些参数都设置为0,则代表不限制,出来客户端类型)
    • 第一个参数指定客户端类型:normal(普通客户端)、slave(从节点伪装客户端)、pubsub(发布订阅客户端)
    • 第二个参数指定缓冲区的最大内存,若超过时,就会强制断开连接
    • 第三和四个参数指定缓冲区超过第三个参数设置的大小,并且持续了第四个参数的时间,就会强制断开连接
    • 默认值如下
client-output-buffer-limit normal 0 0 0

#普通客户端无限制,所以要节制使用monitor命令
client-output-buffer-limit slave 256mb 64mb 60

#可能主从延迟较高,或者从节点数量过多时,主从复制容易发生阻塞,缓冲区会快速打满,最终导致全量复制

#所以可以多设置些,从节点也不要过多
client-output-buffer-limit pubsub 32mb 8mb 60

#生产速度大于消费速度,缓冲区会打满
  • 输入缓冲区:就是执行命令的队列,每个客户端都是不同的,最大是1G,超过后会强制断开连接,不可动态设置
客户端信息查看
  • info clients命令可以查看已连接的客户端的统计信息
字段名 含义
connected_clients 已连接客户端的数量(不包括通过从属服务器
client_longest_output_list 当前连接的客户端当中,最长的输出列表
client_longest_input_buf 当前连接的客户端当中,最大的输入缓存
blocked_clients 正在等待阻塞命令(BLPOP、BRPOP)的客户端数量
  • client list可查看每个客户端的详细信息
字段名 含义
id 客户端连接的唯一标识
addr 客户端的地址和端口
fd 套接字所使用的文件描述符,-1表示该客户端为redis内部客户端
age 以秒计算的已连接时长
idle 以秒计算的空闲时长
flags 客户端flag
O:客户端是monitor模式下的附属节点(slave)
S: 客户端是一般模式(normal)下的附属节点
M:客户端是主节点(master)
x: 客户端正在执行事务
b: 客户端正在等待阻塞事件
i: 客户端正在等待VM I/O操作(已废弃)
d: 一个受监视(watched)的键已被修改,EXEC命令将失败
c: 将恢复完整地写出之后,关闭连接
u: 客户端未被阻塞(unblocked)
A: 尽可能快地关闭连接
N:未设置任何flag
db 该客户端正在使用的数据库ID
sub 已订阅频道的数量
psub 已订阅模式的数量
multi 在事务中被执行的命令数量
qbuf 查询缓冲区的长度(单位为字节,0表示没有分配查询缓冲区)
qbuf-free 查询缓冲区剩余空间的长度(单位为字节,0表示没有剩余空间)
obl 输出缓冲区的长度(单位为字节,0表示没有分配输出缓冲区)
oll 输出列表包含的对象数量(当输出缓冲区没有剩余空间时候,命令回复会以字符串对象的形式被入队到这个队列里)
omem 输出缓冲区和输出列表占用的内存总量
events 文件描述符事件
r: 客户端套接字(在事件loop中)是可读的(readable)
w:客户端套接字(在事件loop中)是可写的(writeable)
cmd 最近一次执行的命令

复制缓冲区

在主从复制中适当调大repl-backlog-size配置项(默认1mb),牺牲一下内存可以避免全量复制的开销,具体原理在主从复制中

AOF缓冲区

若开启AOF备份,无论是哪种更新策略,都是先将命令放入缓冲区,之后在刷新到文件中,另外在AOF重写时,还会单独分配一个AOF重写缓冲区,AOF缓冲区没有任何容量限制,也没有任何可配置的配置项

内存碎片

内存碎片是必然存在的,因为Resis使用的是jemalloc内存分配器,是按照内存块进行分配的,可能会分配多一点内存,用不完产生的内存碎片,为了更好的性能,未用完的内存不会马上返还给OS,从而实现提高性能

减少内存碎片的方式:

  • 避免频繁更新操作:append、setrange等
  • 重启redis服务:最好是已经实现高可用的集群中将主节点重启,从节点会立刻顶替上来
  • redis4.0以上可以设置自动清理config set activedefrag yes,也可以通过memory purge手动清理,配置监控使用性能最佳

内存管理

  • 内存设置上限:使用maxmemory配置项,可动态配置,配置Redis实例最大内存,只能限制key和value的存储内存,对于其他内存无法限制,比如客户端缓冲区、子进程等,所以一般要保留30%的自由内存

  • 内存回收策略:

    • 删除过期键策略
      • 惰性删除:访问key,在设置过期时间的key字典中查找是否过期,查到过期再删除,并返回nil
      • 定时采样删除:定期对设置过期时间的key字典进行扫描(每秒十次),进行采样删除(选20个样本),若有25%的键都过期了,就会进入更快的采样删除算法进行删除过期键
    • 内存溢出控制策略:配置maxmemory-policy配置项,对超过最大内存时对应的的key的淘汰策略
淘汰策略 含义
noeviction 默认策略,当内存使用达到阈值的时候,所有引起申请内存的命令会报错
volatile-lru 在设置了过期时间key中,优先移除全部时间段内最近最少使用的key
allkeys-lru 在所有key中,优先移除全部时间段内最近最少使用的key
volatile-lfu 在设置了过期时间key中,优先移除某时间段内最近最少使用的key
allkeys-lfu 在所有key中,优先移除某时间段内最近最少使用的key
volatile-random 在设置了过期时间key中,随机移除某个key
allkeys-random 在所有key中,随机移除某个key
volatile-ttl 在设置了过期时间的键空间中,优先移除更早过期时间的key
此作者没有提供个人介绍
最后更新于 2022-11-07