redis在执行命令之前, 根据对象的类型来判断一个对象是否可以执行给定的命令.

使用对象的另一个好处是, 我们可以针对不同的使用场景, 为对象设置多种不同的数据结构实现, 从而优化对象在不同场景下的使用效率.

除此之外, redis的对象系统还实现了基于引用计数技术的内存回收机制, 当程序不再使用某个对象的时候, 这个对象所占用的内存就会被主动释放.

脑洞, 每个进程都有自己的文件描述符表, 所有进程共享一张文件表

另外, redis还通过引用计数技术实现了对象共享机制, 这一机制可以在适当的条件下, 让多个数据库键共享一个对象来节约内存.

最后, redis的对象带有访问时间记录信息, 该信息可以用于计算数据库键的空转时长, 在服务器启用了maxmemory的情况下, 空转时间较大的那些键可能会优先被删除

所以实现的是lru??

对象的类型与编码

redis使用对象来表示数据库的key和value, 每当在redis新建一个键值对的时候, 会至少创建两个对象, 一个键对象, 一个value对象.

么个对象都是一个redisObject对象, 格式类似于:

1
2
3
4
5
6
7
8
9
10
11
typedef struct redisObject {
// 类型
unsigned type:4;
// 编码
unsigned encoding:4;
// 指向底层实现数据结构的指针
void *ptr;

//
...
} robj;

redis可以用过type和object encoding查看一个对象的类型和编码方式

1
2
3
4
5
6
7
8
9
10
11
12
127.0.0.1:6379> set msg "haha"
OK
127.0.0.1:6379> type msg
string
127.0.0.1:6379> RPUSH numbers 1 2 3 4 5
(integer) 5
127.0.0.1:6379> type numbers
list
127.0.0.1:6379> OBJECT encoding msg
"embstr"
127.0.0.1:6379> OBJECT encoding numbers
"quicklist"

retis通过encoding属性来设置对象使用的编码方式, 而不是用特定的类型的对象关联一种固定的编码, 这样redis可以根据不同的使用场景选择不同的编码, 在某一场景下可以优化:

  • 列表包含的元素比较少的时候, redis使用压缩列表作为列表对象的底层实现:
    • 因为压缩列表比双端列表更节约内存, 并且元素较少的时候在内存中以连续快方式保存的压缩列表比双端列表可以更快的被载入到内存中..所以是因为读取是分快的还是什么原因????
    • 随着列表的逐渐增大, 压缩列表的优势收缩, 然后采用双端链表实现

字符串对象