降低Redis内存占用之短结构

降低Redis内存占用的方法——使用短结构存储数据和对数据进行分片。

  降低Redis内存占用有助于减少创建快照和加载快照所需的时间、提升载入AOF文件和重写AOF文件时的效率、缩短从服务器同步所需的时间,并能让Redis存储更多的数据。

Redis为列表、集合、散列和有序集合提供了一组配置选项(配置文件中),这些选项可以让Redis以更加节约空间的方式存储长度较短的结构(即短结构)。

  在列表、散列和有序集合的长度较短或者体积较小的时候,Redis可以选择使用一种名为压缩列表(ziplist)的紧凑存储方式来存储这些结构。压缩列表会以序列化的方式存储数据,这些序列化数据每次被读取的时候都要就行解码,每次被写入的时候都要进行局部的重新编码,并且可能需要对内存里的数据进行移动。因此读写一个长度较大的压缩列表可能会给性能带来负面的影响。

来看一下不同结构使用压缩列表表示的配置选项:

list-max-ziplist-entries 512
list-max-ziplist-value 64          当列表的元素长度都小于64字节并且列表元素数量小于512时,使用压缩列表,反之使用linkedlist。

hash-max-ziplist-entries 512
hash-max-ziplist-value 64          当散列的元素的键和值都小于64字节并且键值对的数量小于512时,使用压缩列表,反之使用hashtable

zset-max-ziplist-entries 128
zset-max-ziplist-value 64          当有序集合的元素都小于64字节并且元素数量小于128个的时候,使用压缩列表,反之使用skiplist

-max-ziplist-entries:表示列表、散列和有序集合在被编码为压缩列表的情况下,允许包含的最大元素数量。

  -max-ziplist-value:表示压缩列表的每个节点的最大体积是多少 。

  列表、散列和有序集合的基本配置选项很相似,它们都由-max-ziplist-entries和-max-ziplist-value组成。当这些选项设置的限制条件中的任意一个被打破的时候,Redis就会将相应的列表、散列或者有序集合从压缩列表编码转换为其他结构,而内存的占用也会因此增加。

redis 127.0.0.1:6379> RPUSH test a b c d
(integer) 4
redis 127.0.0.1:6379> DEBUG OBJECT test
Value at:000000000384B498 refcount:1 encoding:ziplist serializedlength:24 lru:1503687 lru_seconds_idle:60
redis 127.0.0.1:6379> RPUSH test abc
(integer) 5
redis 127.0.0.1:6379> DEBUG OBJECT test
Value at:000000000384B498 refcount:1 encoding:ziplist serializedlength:29 lru:1503695 lru_seconds_idle:10
redis 127.0.0.1:6379> RPOP test
"abc"
redis 127.0.0.1:6379> DEBUG OBJECT test
Value at:000000000384B498 refcount:1 encoding:ziplist serializedlength:24 lru:1503697 lru_seconds_idle:10

上面的图中,首先推入4个元素到test列表,然后通过debug object命令查看“test”的相关信息,可以发现“test”的存储结构为ziplist(压缩列表),当推入一个超出编码允许大小的元素时,“test”的存储结构将从ziplist转换为linkedlist,而且即使将超出编码允许大小的元素弹出后,列表test的存储结构也不会重新转换为压缩列表。

  跟列表、散列和有序集合一样,体积较小的集合也有自己的短结构:如果集合包含的所有成员都可以被解释为十进制整数,而这些整数又处于平台的有符号整数范围之内,并且集合成员的数量满足配置文件中的限制条件,那么Redis就会以有序整数数组的方式存储集合。这种存储方式又被称为整数集合(intset)。

  我们先来看一下集合使用整数集合表示的限制条件:

set-max-intset-entries 512  --只要集合存储的整数数量没有超过512,Redis就会使用整数集合表示以减少数据的体积。

再来看一下操作实例:

redis 127.0.0.1:6379> SADD testset 1 2 3 4 5 6 7 8 9 10
(integer) 10
redis 127.0.0.1:6379> debug object testset
Value at:000000000384B3B8 refcount:1 encoding:intset serializedlength:29 lru:1503715 lru_seconds_idle:10
redis 127.0.0.1:6379> sadd testset 11
(integer) 1
redis 127.0.0.1:6379> debug object testset
Value at:000000000384B3B8 refcount:1 encoding:intset serializedlength:31 lru:1503717 lru_seconds_idle:10

为了方便测试,我将set-max-intset-entries设置为10,首先向集合testset中加入10个整数元素,testset的存储结构为intset(整数集合),当再向testset中增加一个整数元素时,此时集合元素数量超过了set-max-intset-entries的设置,此时testset的存储结构将从整数集合(intset)转换为散列表(hashtable)。

  前面提到过,读写一个长度较大的压缩列表可能会给性能带来负面的影响,同样,操作一个元素数量较多的整数集合时也可能会给性能带来负面影响,所以Redis才会在压缩列表和整数集合突破限制条件时,将其转换为更底层的结构类型。

联系我们

邮箱 626512443@qq.com
电话 18611320371(微信)
QQ群 235681453

Copyright © 2015-2024

备案号:京ICP备15003423号-3