redis内存优化


redis内存优化

文章插图
 
小的聚合类型数据的特殊编码处理
redis2.2版本及以后,存储集合数据的时候会采用内存压缩技术,以使用更少的内存存储更多的数据 。如Hashes,Lists,Sets和Sorted Sets,当这些集合中的所有数都小于一个给定的元素,并且集合中元素数量小于某个值时,存储的数据会被以一种非常节省内存的方式进行编码,使用这种编码理论上至少会节省10倍以上内存(平均节省5倍以上内存) 。并且这种编码技术对用户和redis api透明 。因为使用这种编码是用CPU换内存,所以我们提供了更改阈值的方法,只需在redis.conf里面进行修改即可.
hash-max-zipmap-entries 64 (2.6以上使用hash-max-ziplist-entries)hash-max-zipmap-value 512 (2.6以上使用hash-max-ziplist-value)list-max-ziplist-entries 512list-max-ziplist-value 64zset-max-ziplist-entries 128zset-max-ziplist-value 64set-max-intset-entries 512(集合中)如果某个值超过了配置文件中设置的最大值,redis将自动把把它(集合)转换为正常的散列表 。这种操作对于比较小的数值是非常快的,但是,如果你为了使用这种编码技术而把配置进行了更改,你最好做一下基准测试(和正常的不采用编码做一下对比).
使用32位的redis
使用32位的redis,对于每一个key,将使用更少的内存,因为32位程序,指针占用的字节数更少 。但是32的redis整个实例使用的内存将被限制在4G以下 。使用make 32bit命令编译生成32位的redis 。RDB和AOF文件是不区分32位和64位的(包括字节顺序),所以你可以使用64位的reidis恢复32位的RDB备份文件,相反亦然.
位级别和字级别的操作
Redis 2.2引入了位级别和字级别的操作: GETRANGE, SETRANGE, GETBIT 和 SETBIT.使用这些命令,你可以把redis的字符串当做一个随机读取的(字节)数组 。例如你有一个应用,用来标志用户的ID是连续的整数,你可以使用一个位图标记用户的性别,使用1表示男性,0表示女性,或者其他的方式 。这样的话,1亿个用户将仅使用12 M的内存 。你可以使用同样的方法,使用 GETRANGE 和 SETRANGE 命令为每个用户存储一个字节的信息 。这仅是一个例子,实际上你可以使用这些原始数据类型解决更多问题 。
尽可能使用散列表(hashes)
小散列表(是说散列表里面存储的数少)使用的内存非常小,所以你应该尽可能的将你的数据模型抽象到一个散列表里面 。比如你的web系统中有一个用户对象,不要为这个用户的名称,姓氏,邮箱,密码设置单独的key,而是应该把这个用户的所有信息存储到一张散列表里面.
如果你想了解更多关于这方面的知识,请读下一段.
使用散列结构高效存储抽象的键值对
我知道这部分的标题很吓人,但是我将详细解释这部分内容.
一般而言,把一个模型(model)表示为key-value的形式存储在redis中非常容易,当然value必须为字符串,这样存储不仅比一般的key value存储高效,并且比memcached存储还高效.
让我们做个对比:一些key存储了一个对象的多个字段要比一个散列表存储对象的多个字段占用更多的内存 。这怎么可能?从原理上讲,为了保证查找一个数据总是在一个常量时间内(O(1)),需要一个常量时间复杂度的数据结构,比如说散列表.
但是,通常情况下,散列表只包括极少的几个字段 。当散列表非常小的时候,我们采用将数据encode为一个O(N)的数据结构,你可以认为这是一个带有长度属性的线性数组 。只有当N是比较小的时候,才会采用这种encode,这样使用HGET和HSET命令的复杂度仍然是O(1):当散列表包含的元素增长太多的时候,散列表将被转换为正常的散列表(极限值可以在redis.conf进行配置).
无论是从时间复杂度还是从常量时间的角度来看,采用这种encode理论上都不会有多大性能提升,但是,一个线性数组通常会被CPU的缓存更好的命中(线性数组有更好的局部性),从而提升了访问的速度.
既然散列表的字段及其对应的值并不是用redis objects表示,所以散列表的字段不能像普通的key一样设置过期时间 。但是这毫不影响对散列表的使用,因为散列表本来就是这样设计的(我们相信简洁比多功能更重要,所以嵌入对象是不允许的,散列表字段设置单独的过期时间是不允许的).
所以散列表能高效利用内存 。这非常有用,当你使用一个散列表存储一个对象或者抽象其他一类相关的字段为一个模型时 。但是,如果我们有一个普通的key value业务需求怎么办?


推荐阅读