Redis 提供了很多关于优化内存的方法, 上面这些配置的值都是默认配置, 实际要根据我们具体的需求场景来调节, 并要做大量的测试, 以达到最优的效果. 同时必须对 Redis 这些数据结构有很好的理解.
zipmap 优化 hash
将一个对象存储在 hash 类型中会占用更少的内存, 并且可以更方便的存取整个对象. 省内存的原因是新建一个 hash 对象时开始是用 zipmap 来存储的. 这个 zipmap 其实并不是 hash table, 但是 zipmap 相比正常的 hash 实现可以节省不少 hash 本身需要的一些元数据存储开销. 尽管 zipmap 的添加, 删除, 查找都是 O(n), 但是由于一般对象的 field 数量都不太多. 所以使用 zipmap 也是很快的, 也就是说添加删除平均还是 O(1).
如果 field 或者 value 的大小超出一定限制后, redis 会在内部自动将 zipmap 替换成正常的 hash 实现. 这个限制可以在配置文件中指定(默认配置在 redis 根目录下的 redis.conf 中):
- hash-max-zipmap-entries 512 #配置字段最多 512 个
- hash-max-zipmap-value 64 #配置 value 最大为 64 字节
ziplist 优化 list
如果 redisObject 的 type 成员值是 REDIS_LIST 类型的, 则当该 list 的元素个数小于配置值 list-max-ziplist-entries, 且元素值字符串的长度小于配置值 list-max-ziplist-value,
则可以编码成 REDIS_ENCODING_ZIPLIST 类型存储, 否则采用 Dict 来存储(Dict 实际是 Hash Table 的一种实现),list 采用 ziplist 数据结构存储数据, 这样做一方面为了节省内存, 另一方面这种结构式顺序存储的结构, 能够更好利用 cpu local 和预取策略.
配置如下所示:
- list-max-ziplist-entries 512 #配置元素个数最多 512 个
- list-max-ziplist-value 64 #配置 value 最大为 64 字节
intset 优化 set
当 set 集合中的元素为整数且元素个数小于配置 set-max-intset-entries 值时, 使用 intset 数据结构存储, 否则转化为 Dict 结构, Dict 实际是 Hash Table 的一种实现, key 为元素值, value 为 NULL, 这样即可在 O(1)时间内判断集合中是否包含某个元素.
intset 中有三种类型数组: int16_t 类型, int32_t 类型, int64_t 类型. 至于怎么选择是那种类型的数组, 是根据其保存的值的取值范围来决定的, 初始化时是 int16_t, 根据 set 中的最大值在 [INT16_MIN, INT16_MAX] , [INT32_MIN, INT32_MAX], [INT64_MIN, INT64_MAX] 的那个取值范围来动态确定整个数组的类型. 例如 set 一开始是 int16_t 类型, 当一个取值范围在 [INT32_MIN, INT32_MAX]的值加入到 set 时, 则将保存 set 的数组升级成 int32_t 的数组.
intset 元素限制的配置如下所示:
set-max-intset-entries 512 #配置元素个数最多 512 个
ziplist 优化 sorted set
根 hash 和 list 一样 sorted set 也有节约内存的方式, 当 sorted set 的元素个数及元素大小小于一定限制时, 它是用 ziplist 来存储.
这个限制的配置如下:
- zset-max-ziplist-entries 128 #配置元素个数最多 512 个
- zset-max-ziplist-value 64 #配置 value 最大为 64 字节
小结
Redis 提供了很多关于优化内存的方法, 上面这些配置的值都是默认配置, 实际要根据我们具体的需求场景来调节, 并要做大量的测试, 以达到最优的效果. 同时必须对 Redis 这些数据结构有很好的理解.
来源: http://stor.51cto.com/art/201804/571713.htm