Redis的底层实现---字符串章节,Java面试题最新

      • @ 2杜绝缓冲区溢出

        *   [@ 3减少修改字符串时带来的内存重分配次数](about:blank#___3_81)
        
        *   [@4 二进制安全](about:blank#4_______94)
        
        *   [@5 兼容部分C字符串函数](about:blank#5____C_98)
        
      • 总结

      • About Me

[](

)before

  • C语言基础

  • Redis基础

[](

)导入

redis的命令如下:


 set x "hello";

			get x;

			hello 

Redis作为一种存储字符串的缓存结构,其具体实现是由C语言完成,在C语言中,字符串是通过字符数组实现的,即char[],那么Redis对于字符串的实现是不是也是基于字符数组吗?不是的,Redis对字符串的处理是通过SDS(Simple Dynamic String)实现的。

[](

)SDS介绍

SDS(Simple Dynamic String)简单动态字符串,它是由C语言完成,如下是其具体实现


struct sdshdr{

	//记录buf数组已使用字节的数量

	//等于SDS所保存字符串的长度

	int length; 

	//记录buf数组未使用字节的数量

	int free;

	//buf数组

	char[] buf;

};



看看redis的示例:

	sdshdr

	free 0

	length 5

	buf     -->|‘R‘|‘e‘|‘d‘|‘i‘|‘s‘|‘\0‘|

解释:

		- free为0,表示这个SDS没有分配任何未使用的空间

		- length为5,表示这个SDS保存了一个长度为5的字符串	

		- buf数组中保存着“Redis”字符串 

SDS遵循C字符串以空字符串结尾的惯例,保存空字符串的1字节空间不计算在SDS的len属性之中。

再看看SDS的free不为0的情况:


 sdshdr

	free 3

	length 5

	buf      -->|‘R‘|‘e‘|‘d‘|‘i‘|‘s‘| | | | 

free的值为3,表示这个SDS分配了三个空闲的空间

[](

)SDS与字符串的区别

C语言使用简单的字符串表示方式,并不能满足Redis对字符串在安全性,效率,以及功能方面的要求,SDS更使用Redis。

@1 常数复杂度获取字符串长度

C字符串:

因为C语言并不记录自身的长度信息,所以获取一个C字符串的长度,程序必须遍历整个字符串,对遇到的,每个字符进行计数,直到遇到代表字符串结尾的空字符串为止,这个操作的复杂度为O(n)。

SDS:

与C语言不同的是,SDS结构中的属性length记录了SDS本身的长度,所以获取一个SDS长度的复杂度为O(1)。有人疑问那么SDS的length值是哪来的?这里的length值是SDS API在设置和更新SDS时自动完成的。

总结1:通过使用SDS而不是C字符串,Redis获取字符串长度的复杂度由O(N)降为O(1),这确保了字符串长度的获取的工作不会成为Redis的性能瓶颈。

[](

)@ 2杜绝缓冲区溢出

C字符串:

由于C自身不记录字符串的长度带来一个问题是容易造成缓冲区溢出(buffer overflow)。在<string.h>/strcat函数中,可以将一个字符串拼接到另外一个字符串的末尾。

char *strcat(char *dest,const char *src)

理想状态下,用户在使用这个函数时,假定C为dest分配了足够多的内存,可以容纳src字符串中的所有内容,而一旦这个假定不成立,就会产生缓冲区溢出。举个例子,假定内存中有相邻的两个字符串s1,s2,如图:

总结

这个月马上就又要过去了,还在找工作的小伙伴要做好准备了,小编整理了大厂java程序员面试涉及到的绝大部分面试题及答案,希望能帮助到大家

CodeChina开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频】

Redis的底层实现---字符串章节,Java面试题最新

Redis的底层实现---字符串章节,Java面试题最新

Redis的底层实现---字符串章节,Java面试题最新

上一篇:深入理解Java虚拟机读后感


下一篇:Linux awk命令详解