系列文章:
本机使用redis的相关命令
redis-server ./etc/redis.conf
根据这个配置文件启动redis
ps -ef | grep redis
查看后台redis进程
redis-cli -v 或者 redis-server -v
查看redis的版本号
redis-cli -h host -p port -a password
通过redis客户端连接远程的redis
简单动态字符串SDS
SDS是什么
Redis 是用C语言写的 C字符串是C语言传统的字符串结构,而redis采用一种名为简单动态字符串(simple dynamic string, SDS)的抽象类型,用作redis的默认字符串结构.
C字符串的结构
C语言使用长度为N+1的字符数组来表示长度为N的字符串,并且字符数组最后一个元素总是空字符’\0’,c语言就是通过空字符来判断是不是一个字符串的结尾.
SDS的结构
sdshdr 是结构体的名称
Free 是SDS分配了内存空间,但是没有使用的长度
Len 是SDS保存的字符串数组的长度,注意这个长度不包括最后那个空字符’/0’
Buf 是一个char类型的数组,包含了SDS的具体内容,以及最后一个字节保存了空字符’/0’
SDS最后的空字符’/0’不计算在len长度内,是因为SDS末尾加这个,是为了复用一部分C字符串的函数.同时为SDS的空字符分配额外的1字节空间,以及将空字符添加到字符数组中都是SDS函数自动完成的.最重要的是,SDS不会通过这个空字符来区分不同的字符串,因此这个空字符对于使用者来说是完全不需要关心的.
SDS字符串这么设计的好处
1.常数复杂度获取字符串长度
C字符串获取字符串长度的方法是遍历整个字符串,对遇到的每个字符进行计数,直到遇见代表截止的空字符’/0’ SDS直接通过len属性 获取字符串的长度 len属性是SDS在创建或更新时自动设置的 因此使用SDS将获取字符串的复杂度从O(N)降低到了O(1).redis中键一定是字符串,使用SDS实现.因此我们在对一个很长的字符串键执行STRLEN命令的时候,不会对系统性能造成任何影响,确保了获取字符串长度不会成为Redis的性能瓶颈.
2.杜绝缓冲区溢出
C字符串本身不记录自身的长度,在字符串拼接的时候,如果不预先分配好所需要的内存,直接进行拼凑,就可能会产生缓冲区溢出的问题. SDS在修改字符串的时候,会首先检查SDS的空间是否满足修改的需求(根据len 和 free属性),然后才执行实际的修改,就杜绝了缓冲区溢出的可能.
3.减少了修改字符串带来的内存重新分配的次数
C字符串在修改字符串后(指长度发生变化),内存需要重新分配(增大或减少),修改N次,必须重新分配N次 SDS利用len和free属性采用下面的策略,最多重新分配N次
1.空间预分配
用于优化SDS字符串增长操作,当增加SDS字符串长度,并且必须进行内存扩展的时候,有以下两种情况:
如果SDS修改后的长度小于1Mb,那么会为SDS的free属性赋值一个和当前len相同的值,就说明SDS当前得到的内存空间,一半使用了,另一半是空置的等待使用,此时如果再次修改这个SDS,如果free+len的空间足够满足修改后的结果,就不需要再次分配空间,减少了一次分配空间的次数.
如果SDS修改后的长度大于等于1Mb,那么会给SDS的free属性赋值1Mb的未使用空间. 采用空间预分配的策略,redis可以减少连续执行字符串增长所需的内存分配次数,如果修改N次字符串的话,至多需要分配N次内存.
2.惰性空间释放
用于优化SDS字符串的缩短操作,当需要缩短SDS保存的字符串时,内存并不会立即回收缩短后多出来的空间,而是使用free属性记录这些多余的空间,等待将来的使用.
例如一个SDS的len为13 free为0, 缩短后SDS的len为7,free变为6,这个过程中不存在内存重新分配的过程.
SDS提供了相应的API 能够真正的释放SDS的free空间,不用担心内存浪费.
4.二进制存储
C字符串按照空字符’/0’来作为字符串的结尾,区分不同的字符串,就使得C字符串只能保存文本数据,而不能保存图片,音频,视频,压缩文件这样的二进制数据.
例如这个二进制数据Redis cluster,C字符串只能识别到Redis SDS区分不同的字符串是通过len属性,因此可以保存任意格式的二进制数据.