Redis Memory

Redis 内存

Posted by John-zero on November 20, 2017

内存监控

info 监控 (V4.01)

类型 属性 描述
Clients    
  connected_clients 已连接客户端的数量
Memory    
     
  used_memory 由 Redis 分配器分配的内存总量, 以字节 (byte) 为单位
  used_memory_rss 从操作系统的角度, 返回 Redis 已分配的内存总量 (俗称常驻集大小)
  mem_fragmentation_ratio used_memory_rss 和 used_memory 之间的比率
一般重点关注: used_memory, used_memory_rss, mem_fragmentation_ratio

客户端监控

client list

注意 输入缓冲区 qbuf (总容量), qbuf-free (剩余容量)

	Redis 会为每个客户端都分配输入缓冲区, 也就是将客户端发送的命令临时保存, 等 Redis 来获取执行 
	
	造成该缓冲区过大的原因一般是 Redis 的处理速度跟不上输入缓冲区的输入速度, 
		并且每次输入缓冲区的命令还包含了大量的 bigkey 对象

	该缓冲区使用不当会导致
		该缓冲区大小不能超过 1G, 不然会导致客户端连接被关闭
		该缓冲区不受 maxmemory 控制

注意 输出缓冲区 obl (固定缓冲区长度), oll (动态缓冲区列表长度), omem (使用字节数)	

	Redis 会为每个客户端都分配输出缓冲区, 也就是将命令的执行结果返回给客户端, 等 Redis 和 客户端交互返回结果提供缓冲
	
	obl 返回比较小的执行结果 (使用的是 字节数组 缓存)
	
	oll 返回比较大的执行结果 (使用的是 列表 缓存), 比如 HGETALL, SMEMBERS 等
	
注意客户端存活状态
	
	age 客户端连接的时间
	idle 最近一次空闲时间
	
	如果最近一次空闲时间太大, 那么就可以考虑优化客户端的连接数, 减少客户端连接数量

内存消耗

内存消耗主要包括: 自身内存 + 对象内存 + 缓冲内存 + 碎片内存.
	而缓冲内存主要包括: 客户端缓冲, 复制积压缓冲区, AOF 缓冲区.
	
键值对象
	压缩, 精简设计, 序列化
缓冲区内存
内存碎片

内存分配

内存分配方式: jemalloc (默认), glibc, tcmalloc
	jemalloc 
		着重于减少内存碎片和支持可伸缩的并发性
		基于申请内存的大小把内存分配分为三个等级:  (对于 64位 系统, 一般页大小为 4K, chunk 大小为 4M)
			Small 的 size 以 8byte, 16 [规则: 16, 32, 48, ..., 128], 32, 64, 128, 256, 512分隔开, 小于页大小
			Large 的 size 以分页 [规则: 4KiB, 8, 12, ..., 4072]为单位, 等差间隔排列, 小于 chunk 的大小
			Huge 的大小是 chunk [规则: 4MiB, 8, 12, 16, ...] 大小的整数倍
	glibc
		...
	tcmalloc
		...

内存管理和分配
	动态内存管理方式
		最大的好处就是能够较为充分的利用内存空间, 减少内存碎片化, 
		与此同时带来的劣势就是容易引起频繁的内存抖动
		通常采用 "空间预分配" 和 "惰性空间释放" 两种优化策略来减少内存抖动
	内存管理的优化
		最基本的出发点就是浪费一点空间还是牺牲一些时间的权衡
		像 STL, tcmalloc, protobuf3的arena机制等采用的核心思路都是 "预分配迟回收"

内存碎片

内存碎片解决方案:
	安全重启, 重启节点可以对内存碎片重新规整. 
		比如 Sentinel 或者 Cluster, 将碎片率过高的主节点切为从节点, 进行安全重启	

内存限制

Redis 默认是无限使用服务器内存

在 redis.conf 中 maxmemory 来限制内存, 
需要注意的是该值限制的只是 Redis 实际使用的内存量, 也就是 used_memory
由于内存碎片的存在, 实际消耗的内存可能远比 maxmemory 设置的更大.

内存回收策略

删除到达过期时间的键对象
	惰性删除: 客户端读取带有超时属性的键时会主动检查是否过期, 过期则删除该键并返回空
	定时任务删除: 10秒运行间隔的定时任务, 根据键的过期比率和使用快慢两种速率模式回收键

内存溢出控制策略

内存所使用达到 maxmemory 上限时触发内存溢出的控制策略
	在 redis.conf 中 maxmemory-policy 策略控制
		noeviction: 默认策略, 不删除数据, 拒绝写响应读, 写返回 (error) OOM command not allowed when used memory
		volatile-lru: 根据 LRU 算法删除设置了超时属性的键, 直到腾出足够空间为止
			如果没有可删除的键对象, 回退到 noeviction 策略
		allkeys-lru: 根据 LRU 算法删除键, 不管有没有设置超时属性, 直到腾出足够空间为止
		allkeys-random: 随机删除所有键, 直到腾出足够空间为止			
		volatile-random: 随机删除过期键, 直到腾出足够空间为止
		volatile-ttl: 根据键值对象的 TTL 属性, 删除最近将要过期数据
			如果没有可删除的键对象, 回退到 noeviction 策略

内存优化

1. scan + object idletime 命令批量查询哪些键长时间未被访问, 然后对其进行删除清理
2. 压缩 KEY 和 VALUE
	二进制压缩 (Google Protostuff, kryo, hessian)
	JSON (压缩: Google Snappy, GZIP)
	XML
3. ...