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 |
内存消耗划分
- 子进程的内存消耗:bgsave、bgrewriteaof命令
- 系统占用内存:used_memory_rss参数,申请内存的会超过实际使用内存
- 实际消耗内存:used_memory参数
内存优化
客户端缓冲区
配置
- 输出缓冲区:就是命令的返回结果,每个客户端都是不同的,可通过
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 |
Comments NOTHING