Redis原理 — 小对象压缩

Redis原理 — 小对象压缩

使用 32bit 替换 64bit 编译

如果部署 Redis 机器的内存不超过 4G,可以使用 32bit 进行编译,内存所有数据结构的指针空间大小会减少一半,可以达到节约内存的目的。

压缩列表 ziplist

在数据量较少的情况下,Redis 内部会采用一种叫做 ziplist 的数据结构,它会使用 紧凑存储 的方式压缩存储。

以 HashMap 为例,HashMap 使用的是一个二维数组的结构,当数据量较少的情况,数据比较分散,查询效率反而会比一维的结构要慢,另外还会浪费空间。

ziplist 是一个 字节数组,它是一个一维数组,前几个元素存储的当前数组的一些元数据。存储的每个元素之间都是紧挨着的:

ziplist数据结构

如果存储的是 hash 结构,key 和 value 会作为两个 entry 相邻存储

hash以ziplist存储

如果存储的是 zset,score 和 member 会作为两个 entry 相邻存储

zset以ziplist存储

整数型紧凑结构 intset

intset 数据结构是 set 的紧凑型结构,用于存储数据量小且元素都是整数的 set 集合。

如果整数可以用 uint16 表示,intset 的元素就是 16 位数组;如果新加入的整数大于 uint16,就用 uint32 表示,redis 支持 set 集合从 unit16 升级到 unit32 再到 unit64.

inset & hashtable

如果存储的是字符串,inset 会升级为 hashtable。

存储界限

当某个结构的数据量超过 n,或者 key/value 的长度大于 n 时,数据结构由紧凑型升级为标准型。

hash-max-ziplist-entries 512    # hash 的元素个数超过 512 升级为标准存储结构
hash-max-ziplist-value 64       # hash 任意 key/value 长度超过 64 升级为标准存储结构

list-max-ziplist-entries 512    # list 的元素个数超过 512 升级为标准存储结构
list-max-ziplist-value 64       # list 任意元素的长度超过 64 升级为标准存储结构

zset-max-ziplist-entries 128    # zset 的元素个数超过 128 升级为标准存储结构
zset-max-ziplist-value 64       # list 任意元素的长度超过 64 升级为标准存储结构

set-max-intest-entries 512      # zset 的元素个数超过 512 升级为标准存储结构

内存回收机制

Redis 的删除 key 不是及时的,这是因为:Redis 的所有数据是在内存里的,删除 key 需要回收内存。操作系统是以 内存页 为单位回收内存的,一个页上有多个 key,只要内存页上还有一个 key,内存页就不会回收。

Redis 虽然无法保证立即释放被删除 key 的内存,但是可以使用这些尚未被回收的空闲内存。

内存分配算法

内存分配是指以合理的算法划分内存页,需要考虑内存碎片,兼顾平衡性能和效率。

为了保证自身结构的简化性,Redis 使用的第三方内存分配库。目前可以使用的内存分配和有 jemalloc(facebook) 和 tcmalloc(google),jemalloc 性能稍微要好,故作为默认选择。

info memory

Comments