Redis : 理解内存

1. 内存消耗

1.1 内存使用统计

重点关注的指标:
(1)used_memory_rss:从操作系统角度显示Redis进程占用的物理内存的总量。
(2)used_memory:Redis分配器分配的内存总量,所有数据内存的占用量
(3)mem_fragmentation_ratio= used_memory_rss/used_memory。
如果ratio>1: 表示部分内存没有用于数据存储,而是被内存碎片所消耗。
如果ratio<1:表示操作系统把redis内存sweap到硬盘导致。

1.2 内存消耗划分

Redis 内存消耗主要包括: 自身内存+对象内存+缓冲内存+内存碎片
(1)对象内存是Redis内存占用最大的一块。
(2)缓冲内存包括客户端缓冲,复制积压缓冲区,AOF缓冲区。
(3)Redis默认的内存分配器采用jemalloc。

2. 内存管理

2.1 设置内存上限

(1)使用maxmemory参数限制最大可用内存。由于内存碎片的存在,实际消耗的内存可能比maxmemory大。

2.3 内存回收策略

包括两个策略:
(1)删除过期的对象
a. 惰性删除
当客户端读取带有超时属性的键时,如果已经超过键的过期时间,会自动执行删除操作并返回空。但是这种方式存在内存泄漏问题,如果一个键过期了一直没有被访问将无法得到及时删除,从而导致内存不能及时释放。

b.定时任务删除
Redis内部维护一个定时任务,默认每秒运行10次,流程如下:

  • 定时任务随机检查20个键,发现过期时删除键。
  • 如果检查的键种有25%的键过期了,循环执行回收逻辑直到不足25%。

(2)内存溢出达到maxmemory上限,触发内存溢出控制策略。6种策略如下:

  • noeviction: 默认策略。不删除任何数据,拒绝所有写入操作,返回给客户段:OOM command not allow when used memory。
  • volatile-lru:根据LRU算法删除了有超时属性的键,知道腾出足够空间为止。
  • allkeys-lru:根据LRU算法删除键,不管数据有没有设置超时属性。
  • allkey-random:随机删除所有键,知道腾出足够的空间。
  • volatile-random:随机删除过期键
  • voaltile-ttl:根据ttl属性,删除最近将要过期的数据。

3. 内存优化

3.1 redisObject 对象

(1)Redis 存储的所有值对象在内部定义为redisObject 结构体,redisObject 包括以下字段:

  • type:当前数据使用的数据类型。e.g. string, hash, set, zset, list.
  • encoding 字段:Redis内部编码类型。
  • lru:字段:记录对象最后一次被访问的时间。
  • refcount 字段:记录当前对象被引用次数。
  • ptr 字段:指向数据的指针。

3.2 缩减键值对象

3.3. 共享对象池

3.4 字符串优化

3.4.1 字符串结构

(1)内部使用简单动态字符串(simple dynamic string, SDS)。int len:已用字节长度。int free : 未用字节长度。 char buf[]:字节数组。
(2)注意:尽量减少字符串频繁修改操作如append,setrange,改为直接使用set修改字符串,降低预分配带来的内存浪费

3.5 编码优化

(1)Redis 为什么对一种数据结构实现多种编码方式?
通过不同编码方式实现空间和实现效率上的平衡。
(2)转化规则只能从小内存编码向大内存编码转换。

3.5.3 ziplist 编码

(1)ziplist编码的主要目的是节省内存。
(2)内部结构:zlbytes,zltail,zllen,entry-1,entry-2…zlend。
(3)每个entry: pre_entry_bytes_length,encoding,contents。
(4)zlbytes:记录整个压缩列表所占字节长度。
(5)zltail:记录距离尾节点的偏移量。
(6)zllen:记录压缩节点数量。
(7)entry:记录具体的节点。
(8)pre_entry_bytes_len:记录前一个节点所占空间。
(9)encoding
(10)content:保存节点的值
(11)zlend:记录列表结尾,占用一个字节。

你可能感兴趣的:(Redis)