专栏名称: keep-go-on
今天看啥  ›  专栏  ›  keep-go-on

内存宝贵,拒绝浪费【redis内存优化】

keep-go-on  · CSDN  ·  · 2019-10-18 19:12

文章预览

第一式:聚合类型的内存压缩

Redis 会对聚合类型数据进行内存压缩,使用更少的内存存储更多的数据。

当这些集合中的所有数都小于一个给定的元素,并且集合中元素数量小于某个值时,存储的数据会被以一种非常节省内存的方式进行编码,使用这种编码理论上至少会节省10倍以上内存(平均节省5倍以上内存)。

另外,这种内存压缩的技术,是以CPU换内存,Reids官方给出了修改阈值的方式,这里针对Hashes集合类型进行简要描述,

redis内存压缩配置项:

hash-max-ziplist-entries 512
hash-max-ziplist-value 64 
list-max-ziplist-entries 512
list-max-ziplist-value 64
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
set-max-intset-entries 512

首先Redis的哈希内部编码有ziplist(压缩列表)和hashtable(哈希表)两种。(redis外层hash使用了hashtable,因此Hashes比直接存储key-value 更节省空间)

Ziplist相对于hashtable,优势在于集中存储,更节省空间,比较适用于元素个数比较少,元素长度比较小的数据。而对于元素操作hashtable的复杂度为O(1),ziplist的复杂度为O(n) ,因此说压缩算法是以CPU来换取空间。

通过上面的概念粗略的解释一下hash内存优化的两个配置项:

hash-max-ziplist-entries 512
hash-max-ziplist-value 64 

hash-max-ziplist-entries 表示 hash的filed最大 数量,hash-max-ziplist-value 表示 hash的value的最大长度

当 hash字段的数量和value的长度 都在(两个条件同时满足) 配置的范围之内,使用压缩编码,即ziplist,如果不满足,采用 hashtable

注:redis 聚合类型 Hashes,Lists,Sets,Sorted Sets

第二式:使用bit(位)

Redis 2.2以后开始引入了位级别和字级别的操作: GETRANGE , SETRANGE , GETBIT SETBIT .使用这些命令,你可以把redis的字符串当做一个随机读取的(字节)数组。

例如你有一个应用,用来标志用户的ID是连续的整数,你可以使用一个位图标记用户的性别,使用1表示男性,0表示女性,或者其他的方式。这样的话,1亿个用户将仅使用12 M的内存。你可以使用同样的方法,使用 GETRANGE SETRANGE 命令为每个用户存储一个字节的信息。这仅是一个例子,实际上你可以使用这些原始数据类型解决更多问题。

第三式:多使用Hashes

上面已经说过,redis外层采用hashtable 编码,因此更消耗内存,合理的将一些数据存储为Hashes 可以减少内存使用(ziplist)

第四式:合理设置最大内存

redis 使用C语言编程,由于malloc()函数的问题,Redis并不会轻易将已经释放的内存归还给系统,因此,Redis总占用和maxmemory几乎一样大的内存。

  • 当某些缓存被删除后Redis并不是总是立即将内存归还给操作系统。这并不是redis所特有的,而是函数malloc()的特性。例如你缓存了5G的数据,然后删除了2G数据,从操作系统看,redis可能仍然占用了5G的内存(这个内存叫RSS,即实际使用物理内存),即使redis已经明确声明只使用了3G的空间。这是因为redis使用的底层内存分配器不会这么简单的就把内存归还给操作系统,可能是因为已经删除的key和没有删除的key在同一个页面(page),这样就不能把完整的一页归还给操作系统.
  • 上面的一点意味着,你应该基于你可能会用到的 最大内存 来指定redis的最大内存。如果你的程序时不时的需要10G内存,即便在大多数情况是使用5G内存,你也需要指定最大内存为10G.
  • 内存分配器是智能的,可以复用用户已经释放的内存。所以当使用的内存从5G降低到3G时,你可以重新添加更多的key,而不需要再向操作系统申请内存。分配器将复用之前已经释放的2G内存.
  • 因为这些,当redis的peak内存非常高于平时的内存使用时,碎片所占可用内存的比例就会波动很大。当前使用的内存除以实际使用的物理内存(RSS)就是fragmentation;因为RSS就是peak memory,所以当大部分key被释放的时候,此时内存的 mem_used / RSS 就比较高.

注:如果 maxmemory 没有设置,redis就会一直向OS申请内存,直到OS的所有内存都被使用完

………………………………

原文地址:访问原文地址
快照地址: 访问文章快照
总结与预览地址:访问总结与预览