前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Redis基本数据类型:String

Redis基本数据类型:String

原创
作者头像
阿成的春天和我的太阳
修改2024-08-13 07:48:49
700
修改2024-08-13 07:48:49
举报
文章被收录于专栏:末日狂奔

redis中的字符串底层是使用自定义的SDS数据结构。

Redis是基于C语言编写,而C语言中的字符串其实就是字符数组,它除了二进制不安全外,还缺少额外信息,无法支持一些高级特性(扩容、越界判断等),于是Redis在字符数组的基础之上做了少了变更,形成了SDS结构。

Redis3.2之前的版本中SDS都是如下结构

代码语言:javascript
复制
struct sds {
    int len; // buf中已占用字节数
    int free; // buf中剩余可用字节数
    char buf[]; // 数据空间
};

对比C中的字符串,SDS的有点主要有:

  1. 额外维护了相关的空间使用信息,可以快速获取字符串长度
  2. 因为维护了字符串长度,可以不使用"\0"作为终止字符,所以是二进制安全的

此外,SDS还将柔性数组buf的指针直接暴露,兼容了C语言处理字符串的各种函数

柔性数组(Flexible Array Member,亦称为可变长数组成员)是一种在 C99 标准引入的结构体特性。它允许结构体的最后一个元素定义为一个未指定大小的数组,这样可以在运行时动态地为这个数组分配内存。柔性数组提供了一种灵活的方法来处理变长数据结构,使得内存分配和管理更加方便。

Redis以高性能著称,而其高性能的核心就是完全的内存操作,内存是Redis的立身之本,所以Redis对于内存的使用非常精细,一个典型的例子就是SDS根据不同的数据长度又分成了5种类型,尽量用最合理的数据类型来表示额外的空间信息

一字节有8位,其中3位可以表示小于8的数据范围,5位可以表示小于32的数据范围,Redis将SDS划分成了5种类型,刚好可以用高三位表示,那么对于长度小于32的短字符串,Redis使用了一个字节的标记字段就保存了类型和长度两个信息,其结构如下

代码语言:javascript
复制
struct __attribute__ ((__packed__)) sdshdr5 {
    unsigned char flags; /* 3 lsb of type, and 5 msb of string length */
    char buf[];
};

对于长度大于等于32的字符串,无法继续使用一个字节的标记字段表示,只能额外拿出两个字段来标记长度和容量,不同的是根据范围的不同,这两个字段使用的数据类型会有差异,其具体结构如下

代码语言:javascript
复制
struct __attribute__((__packed__))sdshdr8 {
    uint8_t len; /* 已使用长度,用1字节存储 */
    uint8_t alloc; /* 总长度,用1字节存储*/
    unsigned char flags; /* 低3位存储类型,高5位预留 */
    char buf[]; /*柔性数组,存放实际内容*/
};

struct __attribute__((__packed__))sdshdr16 {
    uint16_t len; /*已使用长度,用2字节存储*/
    uint16_t alloc; /* 总长度,用2字节存储*/
    unsigned char flags; /* 低3位存储类型,高5位预留 */
    char buf[]; /*柔性数组,存放实际内容*/
};

struct __attribute__((__packed__))sdshdr32 {
    uint32_t len; /*已使用长度,用4字节存储*/
    uint32_t alloc; /* 总长度,用4字节存储*/
    unsigned char flags; /* 低3位存储类型,高5位预留 */
    char buf[]; /*柔性数组,存放实际内容*/
};

struct __attribute__((__packed__))sdshdr64 {
    uint64_t len; /*已使用长度,用8字节存储*/
    uint64_t alloc; /* 总长度,用8字节存储*/
    unsigned char flags; /* 低3位存储类型,高5位预留 */
    char buf[]; /*柔性数组,存放实际内容*/
};

不知道你看到这个结构是否会有疑惑:在使用的时候如何能区分出这几种结构呢?

这需要结合一下两点:

  • sds给上层返回的是buf[]的指针,观察上述5种结构,buf[]的前面都是flags字段,拿到flags字段自然就能得知属于那种数据类型
  • __packed__字段告知编译器1字节对齐,相当于保证flagsbuf[]是挨着的,保证我们上述的计算方式可以执行

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档