Redis是一个非常耗费内存的数据库,所有的数据都存在于内存之中。Redis如果使用32bit进行编译,内部数据结构使用的指针空间占用会减少一半,内存不超过4G可以使用32bit进行编译
小对象压缩存
Redis内部管理的集合数据很小时,会使用紧凑存储形式压缩;HashMap是数组+链表的二维结构,如果内部元素比较少,使用二维结构相比而言更浪费空间,不如使用一维数组进行存储,查找时因为使用的是一维结构且元素很少,遍历时有可能比HashMap本身的查找还要快;使用数组来模拟HashMap的增删改查
public class ArrayMap<K, V> {
private List<K> keys = new ArrayList<>();
private List<V> values = new ArrayList<>();
public V put(K k, V v) {
for (int i = 0; i < keys.size(); i++) {
if (keys.get(i).equals(k)) {
V oldv = values.get(i);
values.set(i, v);
return oldv;
}
}
keys.add(k);
values.add(v);
return null;
}
public V get(K k) {
for (int i = 0; i < keys.size(); i++) {
if (keys.get(i).equals(k)) {
return values.get(i);
}
}
return null;
}
public V delete(K k) {
for (int i = 0; i < keys.size(); i++) {
if (keys.get(i).equals(k)) {
keys.remove(i);
return values.remove(i);
}
}
return null;
}
}
Redis ziplist
Redis的ziplist是一个紧凑的字节数组结构,每个元素之间都是紧挨着的,有可能作为list、hash、set在数据较少时候的存储结构;如果ziplist存储的是hash结构,那么key和value会作为两个entry相邻存在一起;如果ziplist存储的是zset,那么value和score会作为两个entry相邻存在一起
Redis intset
Redis的intset是一个紧凑的整数数组结构,用于存放元素都是整数且元素个数较少的set的集合
1、如果整数可以用uint16表示,那么intset的元素就是16位的数组,如果新加入的整数超过了uint16的表示范围,那么就使用uint32表示,如果新加入的元素超过了uint32的表示范围,那么就使用uint64表示,Redis支持set集合动态从uint16升级到uint32,再升级到uint64
2、位宽表示整数的最大值,一个有符号整数最大16位,那么其范围为-2^16 ~ 2^16-1
3、如果set里存储的是字符串,那么sadd立即升级为hashtable结构。Redis中的set类似于Java中的HashSet,HashSet内部是使用HashMap实现的
object encoding [key] #查看key的存储类型
存储界限:当集合对象的元素不断增加,或者某个value值过大,这种小对象存储也会被升级为标准结构
hash-max-zipmap-entries 512 # hash 的元素个数超过 512 就必须用标准结构存储
hash-max-zipmap-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 # zset 的任意元素的长度超过 64 就必须用标准结构存储
set-max-intset-entries 512 # set 的整数元素个数超过 512 就必须用标准结构存储
内存回收机制
可能存在一种情况,Redis占用了10G的内存,当删除了1G的key时内存并没有太大变化。因为操作系统回收内存是以页为单位,如果这个页上有一个key还在使用,那么这页内存就不会被回收。
执行flushdb的时候发现内存确实被回收了,因为Redis db中所有的key都被删除了
内存分配算法
Redis内存分配使用的是jemalloc