前言
朋友们,我是小许,今天我们聊一聊Redis Sting类型!
Redis为开发者提供了丰富的数据类型,而String类型使用的比较广泛一种,使用也比较简便。
你看用下面命令就可以设置和获取Redis字符串值:
redis 127.0.0.1:6379> SET xiaoxu code
OK
redis 127.0.0.1:6379> GET xiaoxu
"code"
Redis 是用 C 语言写的,但是对于Redis的字符串,却不是 C 语言中的字符串(即以空字符’ ’结尾的字符数组),它是自己构建了一种名为 简单动态字符串(simple dynamic string)简称SDS的抽象类型,并将 SDS 作为 Redis的默认字符串表示。
图片
今天的主要内容就来说说Redis 什么使用SDS,然后了解String数据类型底层数据结构、原理和一些注意事项!
Redis 字符串
SDS名为简单动态字符串,它是内部如何设计的,既然是C语言写的为什么不用C语言的字符串呢?
带着这些问题我们继续往下看!
二进制安全性
🙋♂️ 什么是二进制安全性?
二进制安全是指一种数据处理或传输的方式,其中对待数据的处理不会受到数据中包含的二进制数据的影响。在计算机科学和编程中,这个术语通常与字符串的处理有关。
🚩 C语言字符串和Redis SDS的二进制安全性问题对比
C 语言中字符串是以遇到的第一个空字符 来识别是否到末尾,因此其只能保存文本数据,不能保存图片,音频,视频和压缩文件等二进制数据,否则可能出现字符串不完整的问题,所以其是二进制不安全。
Redis SDS(简单动态字符串)允许不受限制地存储和操作任意长度的二进制数据,保证了二进制安全。
C语言字符串的不足
上面我们通过C语言字符串和Redis SDS二进制安全性问题的现象对比,我们知道了C语言字符串只能保存文本数据,不能保存图片,音频,视频和压缩文件等二进制数据。
与Redis的SDS比起来有以下不足:
- • 获取字符串长度的时间复杂度为 n
- • API是不安全的可能造成缓冲区溢出
- • 只能保存文本数据
SDS结构
现在开始进入正题,挖一挖Redis String的底层实现!
我们复制了其中一种SDS类型【sdshdr8】,它在Redis源码中的结构代码如下:
struct __attribute__ ((__packed__)) sdshdr8 {
uint8_t len;
uint8_t alloc;
unsigned char flags;
char buf[];
};
字段说明:
- • len : 记录buf数组中已使用的字节数量
- • alloc : 分配的buf数组长度,不包括头和空字符结尾
- • flags : 标志位,标记当前字节数组是 sdshdr8/16/32/64 中的哪一种,占 1 个字节。
- • buf[] : 字符数组,用于存放实际字符串
图片
定义的这些字段有以下一些好处:
- • 用单独的变量 len 和 free,可以方便地获取字符串长度和剩余空间;
- • 内容存储在动态数组 buf 中,SDS 对上层暴露的指针指向 buf,而不是指向结构体 SDS。因此,上层可以像读取 C 字符串一样读取 SDS 的内容,兼容 C 语言处理字符串的各种函数,同时也能通过 buf 地址的偏移,方便地获取其他变量;
- • 读写字符串不依赖于