Redis-内存管理


前言

本篇介绍了redis内存相关的知识,包括内存消耗,内存管理,内存优化等相关内容


一、内存消耗

1、进程自身的消耗

1.1 自身内存

1.2 对象内存

1.3 缓冲内存

1.3.1 客户端缓冲
	1.查看指令
		redis-cli
		config get client-output-buffer-limit
		返回:“normal x x x slave x x x pubsub x x x”,
		其中第一个normal代表普通客户端,slave代表从客户端,pubsub代表订阅客户端。
		x代表参数,0代表不限制,第一个x表示最大值,第二个是多少秒内最大值(秒在第三个参数配置),如果超过这个最大值就会关闭连接,第三个表示多少秒。单位都是字节
		可以通过:config get maxclients获取最大连接数,默认是10000
		设置这些限制,如设置从客户端:config set client-output-buffer-limit 'slave x x x'
	2.普通客户端
		消耗基本上可以忽略,如果慢连接较多可能会有问题
		可以通过:config get maxclients获取最大连接数,默认是10000
	3.从客户端
	4.订阅客户端
1.3.2 复制积压缓冲区
	根据repl-backlog-size控制参数,默认1MB
1.3.3 AOF缓冲区
	这部分消耗用户无法控制,消耗的内存取决于AOF重写时间和写入命令量
1.3.4 内存碎片
1.默认采用分配器是jemalloc,其他可选:clibc、tcmalloc
2.产生场景:
	(1)频繁更新
	(2)大量过期键删除
3.解决方案:
	(1)数据对齐:如使用固定的类型,或固定长度的字符串等
	(2)安全重启

2、子进程消耗

1.执行AOF/RDB重写时Redis创建子进程内存消耗
2.设置sycl vm.overcommit_memory = 1 //允许内核可以分配所有的物理内存
3.关闭THP,防止copy-on-write期间内存过度消耗

3、查看内存消耗指标

1.在这里插入图片描述
2.当mem_fragmentation_ratio>1时,说明used_rss - used_memory多出的部分内存并没有用于数据存储,而是被内存碎片所消耗,如果两者相差很大,说明碎片率严重
3.当mem_fragmentation_ratio<1时,这种情况一般出现在操作系统把Redis内存交换(Swap)到硬盘导致,出现这种情况时要格外关注,由于硬盘速度远远慢于内存,Redis性能会变得很差,设置僵死
4.重点关注:
used_memory
used_memory_rss
mem_fragmentation_ratio

二、内存管理

1.控制内存上限

1.使用maxmemory控制最大可用参数(默认是无限使用内存),限制内存的目的:
	(1)当超出内存上限时使用LRU等删除策略释放空间
	(2)防止所用内存超过物理机内存
2.查看最大内存限制:config get maxmemory
3.设置最大内存限制:config set maxmemory 8GB(一般不能把内存全部配置上去,要预留内存给操作系统使用,以防止极端情况)

2.回收策略

1.达到maxmemory上限时触发内存溢出控制策略:
	noeviction:默认策略,不会删除任何数据,拒绝所有写入操作并返 回客户端错误信息(error)OOM command not allowed when used memory,此时Redis只响应读操作。 
	volatile-lru:根据LRU算法删除设置了超时属性(expire)的键,直到腾出足够空间为止。如果没有可删除的键对象,回退到noeviction策略。 
	allkeys-lru:根据LRU算法删除键,不管数据有没有设置超时属性, 直到腾出足够空间为止。 
	volitaile-lfu:对设置了过期时间的key,使用lfu算法进行淘汰
	allkeys-lfu:对所有的key,使用lfu算法
	allkeys-random:随机删除所有键,直到腾出足够空间为止。 
	volatile-random:随机删除过期键,直到腾出足够空间为止。 
	volatile-ttl:根据键值对象的ttl属性,删除最近将要过期数据。如果没有,回退noeviction策略。 
2.设置控制策略:config set maxmemory-policy xxx(上述策略名称)
3.淘汰算法
	1.LRU最近最少使用法
	实现方式:
		1.传统方式
		链表+hashmap,链表的长度代表能存储的最大数量,当我们新增一个key或者是访问了一个key,
		就会将该key放到对头,当链表满了就会先删除链尾的的结点,缺点是需要额外的数据结构,比较消耗内存
		2.redis改良方式,随机采样
		随机的从数据库里选取几个值,然后把热度最低的值淘汰,热度值会存在key的LUR属性字段中,保存了一个时间戳的值,
		这个时间戳是一个全局的时钟,每100毫秒会更新一次,如果每次都保存当前时间,计算需要消耗资源,
		所以设置了一个全局时间以提高执行效率。每当key被访问的时候就会把lru属性的值更新为当前全局时间的值(有100毫秒的误差)。
		评估热度,就是将lru属性的值和全局时间做对比,相差越大说明热度越低
	2.LFU(4.0之后加入)最不常用淘汰法
	实现方式:
		key要记录最近被访问的时间和访问的次数(计数器),redis有一个增长因子(每访问多少次,增加一次访问次数);
		同时还有一个衰减因子(用分钟控制,即:每几分钟没有被访问,就会减少访问次数,为的是实现热度的时效性)
	3.前缀说明
		1.volatile
			对设置了过期时间的key做操作
		2.allkeys
			对所有的key做操作

3、过期策略

1.定时过期(实际不怎么使用)
	对于设置了过期时间的key,一旦到了时间就会直接删除,对内存比较友好,但是,设置过期时间会创建一个定时器去监视,会占用CPU的资源去处理过期的key,会影响redis的响应时间和吞吐量
2.惰性过期(实际使用)
	key被访问的时候才判断是否其,过期则删除,节省CPU的资源,但是对内存不友好
3.定期过期(实际使用)
	每隔一段时间,清除一定数量的过期的key,使CPU和内存的消耗达到最佳的效果

三、内存优化

1.操作系统优化

	1.调整内核参数:vm.overcommit_memory
	2.Swappiness
	3.THP
	4.OOM
	5.NTP
	6.TCP backlog

Redis自身优化

	1.RedisObject对象
	2.缩减键值对象
		Key长度:在完整描述业务的情况下,越短越好
		Value长度:删除不必要的属性避免存储无效数据,选择更高效的序列号工具降低字节数组大小
	3.共享对象池
		共享对象池是指Redis内部维护[0-9999]的整数对象池。创建大量的整数 类型redisObject存在内存开销,
		每个redisObject内部结构至少占16字节,甚至超过了整数自身空间消耗。
		所以Redis内存维护一个[0-9999]的整数对象池,用于节约内存。
		使用共享对象池后,相同的数据内存使用降低30%以上。设置了maxmemory并且启用了LRU相关策略,会禁止共享对象池,
		一般只有在使用整数的时候才会使用共享对象池,整数对象池被复用的几率很大,而且整数复杂度比较低,
		不适合hash、list复杂度较高的类型
	4.字符串优化
		Redis没有采用原生C语言的字符串类型而是自己实现了字符串结构,内部简单动态字符串(simple dynamic string,SDS)。
		Redis自身实现的字符串结构有如下特点:
		O(1)时间复杂度获取:字符串长度、已用长度、未用长度。可用于保存字节数组,支持安全的二进制数据存储。内部实现空间预分配机制,降低内存再分配次数。
		惰性删除机制,字符串缩减后的空间不释放,作为预分配空间保留。尽量减少字符串频繁修改操作如append、setrange,改为直接使用set修改字符串,降低预分配带来的内存浪费和内存碎片化。
	5.编码优化
		Redis的内部编码会随着value长度的不同而变化,不同的内部编码占用的内存是不一样:
		数据优先使用整数,比字符串类型更节省空间。优化字符串使用,避免预分配造成的内存浪费。
		使用ziplist压缩编码优化hash、list等结构,注重效率和空间的平衡。使用intset编码优化整数集合。
		使用ziplist编码的hash结构降低小对象链规模。Redis本质是一个数据结构服务器,它为我们提供多种数据结构,
		使用Redis时不要进入一个误区,大量使用get/set这样的API,把Redis当成Memcached使用。
		对于存储相同的数据内容利用Redis的数据结构降低外层键的数量,也可以节省大量内存。
	6.控制键的数量
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值