01Redis中Srting类型的底层实现原理
Redis中没有直接使用C语言的字符串,而是构建了一套自己的抽象类型,名为简单动态字符串,简称SDS。如果你看Redis源码会发现这样一种结构体:SDS的定义len记录buf数组中已经使用字节的数量,也就是SDS类型所保存的字符串的长度。free记录了buf数组中未使用的字节数量buf是存储字节的数组,用于保存字符串从上面的结构我们可以看出:Redis的String类型封装成SDS结构,体现了用空间换时间的算法思想。牺牲了一些空间,来换取更快的查询效率。比如说结构体中len的值5表示这个SDS保存了一个五个字节长的字符串,O(1)的时间复杂度就可以查询出结果。Redis的定位就是数据库层之上的一层缓存层,所以处处都要考虑高效。其实缓存本身也是用空间换时间思想的体现。解决了C字符串容易缓冲区溢出的问题。因为C字符串不记录字符串长度,所以通过C语言的strcat函数拼接字符串的时候,容易造成拼接后的字符串超过了本身申请的字符串的长度,造成缓冲区溢出。SDS就不会出现这个问题空间预分配:在申请空间的时候预先分配好一定长度的空间。当空间不够用的时候,通过SDS提供的API可以重新申请一片更大的空间。惰性释放空间:当申请的空间不再被使用的时候,不是立刻释放空间,而是在SDS中的free属性将这些字节的数量记录下来,等待将来使用二进制安全:封装后的SDS解决了二进制安全问题,所以在Redis的String类型中可以缓存各种类型数据。SDS的API会以处理二进制的方式来处理SDS存放在buf数组里的数据,不会对其中的数据做任何限制、过滤、或假设,数据在写入时是什么样的,它被读取时就是什么样的。总结一下上面所说的,主要是两个核心思想。第一是SDS这种结构的实现;第二是空间换时间的思想。后面也会有文章专门介绍空间换时间、时间换空间两种思想的具体应用。02底层优化方法学习
从上面的介绍我们可以学习到哪些底层优化方法呢?上文反复提到用空间换时间思想,我想大多数开发人员在实际项目开发中都或多或少地使用过这种思想。Redis、Memcache的设计思路就是这种思想的具体体现。除了Redis,MySQL中也有大量运用,比如说索引就是其中之一。在操作系统、计算机体系结构设计中也存在大量这种设计。除了空间换时间,内存预分配、惰性释放也是很好的优化方法。比如说PHP-FPM进程管理方式中的动态方式(Dynamic),启动的时候预先生成N个Worker进程,当访问量增加时可以增加Worker进程的数量,当访问量降下来后再销毁掉或者保留这些增加的Worker进程,方面后面使用。除了以上方法,还有很多值得学习和借鉴的方法,在此不再一一列举。如果这篇文章对你有帮助,欢迎转发给你的朋友,你们可以一起学习成长。如果有错误的地方或者表达不清晰的地方,也欢迎在评论区指出来。大家的支持就是我的动力,希望我们可以一起进步!03
以下是Redis中String命令的介绍,可以结合前面讲的原理来学习这些命令,一定会有不一样的体会。