一文详尽解析Redis的设计原理,看完“碾压”面试官

本文深入解析Redis的设计原理,涵盖RedisObject、SDS、字典、编码方式等核心概念,通过实例解释查找、添加、更新、删除操作及内存管理策略,助你轻松理解Redis内部工作机制。
摘要由CSDN通过智能技术生成

写在前面

本文将Redis的设计原理从基础到设计器全部都有讲解,内容较多,建议先收藏再找个合适的时候阅读

同时我经过多年的收藏目前也算收集到了一套完整的学习资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、Jvm性能调优、Spring,MyBatis,Redis,ActiveMQ、Mycat、Netty、Kafka、Mysql、Zookeeper、Tomcat、Docker、Dubbo、Nginx等多个知识点高级进阶干货,希望对正在学习路上的朋友有一定的参考和帮助

感兴趣的可以后台 私信我 获取免费领取方式,诚意满满!

1.简介

Redis中的每个Key-Value在内存中都会被划分成DictEntry、RedisObject以及具体对象,其中DictEntry又分别包含指向Key和Value的指针(以RedisObject的形式)以及指向下一个DictEntry的指针。

Key固定是字符串,因此使用字符串对象来进行表示,Value可以是字符串、列表、哈希、集合、有序集合对象中的任意一种。

Redis提供了五种对象,每种对象都需要使用RedisObject进行表示。

Redis使用redisObject结构来表示对象(存储对象的相关信息)

 

typedef struct redisObject { unsigned type; unsigned encoding; unsigned lru; int refcount; void *ptr; }robj;

type属性:存储对象的类型(String、List、Hash、Set、ZSet中的一种) encoding属性:存储对象使用的编码方式,不同的编码方式使用不同的数据结构进行存储。 lru属性:存储对象最后一次被访问的时间。 refcount属性:存储对象被引用的次数。 *ptr指针:指向对象的地址。

使用type命令可以查看对象的类型。

使用object encoding命令可以查看对象使用的编码方式。

使用object idletime命令可以查看对象的空转时间(即多久没有被访问,并不会刷新当前RedisObject的lru属性)

使用object refcount命令可以查看对象被引用的次数。

这些命令都是通过Key找到对应的Value再从Value对应的RedisObject中进行获取。

2.字符串

Redis没有直接使用C语言的字符串,而是自定义了一种字符串类型,以对象的形式存在(C语言的字符串只是单纯的字面量,不能够进行修改)

Redis使用sdshdr结构来表示字符串对象(SDS)

 

struct sdshdr { int len; int free; char buf[]; };

len属性:字符串的长度。 free属性:未使用的字节数量。 buf数组:字符串的底层实现用于存储字符。

buf数组中会有\0空字符,该空字符不会记录在len属性中。

SDS相比C语言的字符串

C语言中存储字符串的字节数组其长度总是N+1(最后一个是结束符),因此一旦对字符串进行追加则需要重新分配内存。

为了避免C字符串的这种缺陷,SDS通过未使用的空间解除了字符串长度和底层数组长度之间的关系,在SDS中buf数组的长度不一定就是字符串长度+1,数组里面还可以包含未使用的字节。

通过未使用的空间,SDS实现了空间预分配和惰性空间释放两种策略,从而减少由于字符串的修改导致内存重分配的次数。

空间预分配:用于优化SDS保存的字符串的增长操作,当需要对SDS保存的字符串进行增长操作时,程序除了会为SDS分配所必须的空间以外,还会为SDS分配额外的未使用空间。

惰性空间释放:用于优化SDS保存的字符串的缩短操作,当需要对SDS保存的字符串进行缩短操作时,程序并不会立即使用内存重分配来回收缩短后多出来的字节,而是使用free属性将这些多出来的字节的数量记录出来,等待将来使用。

3.字典

Redis的字典使用散列表作为底层实现,同时字典也是Redis数据库和HashTable编码方式的底层实现。

Redis使用dictht结构来表示散列表

 

typedef struct dictht { dictEntry **table; unsigned long size; unsigned long sizemask; unsigned long used; }dictht;

table属性:散列表。 size属性:散列表的大小。 sizemask属性:用于计算索引值。 used属性:散列表中节点的数量。

Redis的散列表使用链地址法的方式解决散列冲突,最终就是指针数组的形式,数组中的每个元素都是一个指向DictEntry的指针。

Redis使用dictEntry结构来表示散列表中的节点

 

typedef struct dictEntry { void *key; union{ void *val; uint_tu64; int64_ts64; }v struct dictEntry next*; }dictEntry;

key属性:指向Key的指针(即RedisObject) value属性:可以是一个指向Value的指针(即RedisObject)、uint64_t整数、int64_t整数 next属性:指向下一个DictEntry的指针

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值