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压缩包 redis 压缩表存储数据库数据_redis压缩包

Redis intset

Redis的intset是一个紧凑的整数数组结构,用于存放元素都是整数且元素个数较少的set的集合

redis压缩包 redis 压缩表存储数据库数据_i++_02

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