当前位置: 首页 >  互联网技术 >  为什么Redis不直接使用C语言的字符串?看完直接吊打面试官!

为什么Redis不直接使用C语言的字符串?看完直接吊打面试官!

导读:众所周知Redis有以下几种常见的数据类型 String(字符串)、List(列表)、Set(集合)、Hash(哈希)、Sorted.set(有序集合)、Stream(流)、Geo(地理空间索引)、Bitmap(位图)、HyperLogLog(基数统计)等。.我们最常用的就是St

众所周知Redis有以下几种常见的数据类型 String(字符串)、List(列表)、Set(集合)、Hash(哈希)、Sorted set(有序集合)、Stream(流)、Geo(地理空间索引)、Bitmap(位图)、HyperLogLog(基数统计)等。

我们最常用的就是String(字符串)类型,String类型既可以存储字符串,也可以存储数字,甚至可以直接进行数值运算。

redis> set key1 value1
OK

redis> get key1
"value1"

redis> set key 1
Ok 

redis> INCR key
(integer) 2

Redis是使用标准C语言编写的,而Redis String类型底层使用SDS(Simple Dynamic String 简单动态字符串),但是却没有使用C语言字符串使用,这到底是为什么呢?

Redis的优点是快、安全、节省内存,在设计Redis String实现的时候,也深刻的体现了Redis的这三个优点。

提到Redis字符串的优点,需要先看一下C语言字符串的缺点,毕竟没有对比就没有伤害。

1. C语言字符串实现原理

C语言字符串是使用char数组存储,以’\0’作为字符串结束,比如字符串”Redis“在C语言中存储结构就是下面这样:

那么这种存储方式有什么缺点呢?

1.1 不安全

C语言字符串这种特殊规定,就导致无法存储特殊字符。如果某个字符串中间包含’\0’字符,读取字符串的时候就无法读取到完整字符,遇到’\0’就结束了,像下面这样,只能读取到前半部分“Red”。

如果存储到C语言的字符串,无法完整读取,肯定是不安全的,所以C语言无法存储包含特殊字符的字符串(例如二进制数据)。

1.2 查询性能较低

如果想要获取字符串的长度,需要遍历整个字符串,时间复杂度是O(n),查询效率较低。

1.3 存在缓存区溢出风险

开发中最常用的功能是拼接字符串,每次拼接字符串的时候,都要提前进行扩容。如果忘记扩容了,就会出现缓存区溢出。

1.4 扩容性能较差

扩容过程是非常耗时的,而且每次拼接字符串的时候都需要提交扩容。想象一下,如果使用HashMap的时候,每次put操作都需要进行扩容,性能将会差到什么程度。

由于C语言字符串有这么多缺点,而Redis又追求极致性能,所以只能自己实现一套,看一下Redis字符串底层是怎么实现的?

2. SDS底层实现原理

Redis3.0版本之前的底层结构是这样的:

struct sdshdr {
    // 记录buf数组中已使用字节的数量
    // 等于SDS所保存字符串的长度
    int len;

    // 记录buf数组中未使用字节的数量
    int free;

    // 字节数组,用于保存字符串
    char buf[];
};

而最新Redis7.0版本,sds底层结构是这样的,分成5个实现:

为什么会有5种实现呢?

看一下每种实现的len和alloc的类型就明白了,sdshdr8里面的类型是uint8_t,sdshdr16里面的类型是uint16_t,sdshdr32里面的类型是uint32_t,sdshdr64里面的类型是uint64_t,用来存储不同长度的字符串。使用合适的类型,可以节约大量内存。

Redis自己实现的字符串解决了C语言字符串遇到的问题,并且有以下几个优点:

2.1 存储安全

sds简化版的存储结构是这样的:

struct sdshdr {
    // 已经使用的字节数量
    int len;

    // char数组总字节数量
    int alloc;

    // 字节数组,用于保存字符串
    char buf[];
}; 

可以看出,Redis的字符串并不是用’\0’表示结尾,而是使用len记录了字符串的长度。想要取出完整的字符串,只需要遍历len长度即可。

2.2 查询性能较高

Redis的字符串使用len记录了字符串的长度,想要获取整个字符串的长度,无需遍历字符串,只需要查询len值即可,时间复杂度是O(1)。

Redis采用空间换时间的做法,增加了存储空间,加快了查询性能。

2.3 避免缓存区溢出

Redis的字符串使用len记录了字符串的长度,使用alloc记录整个数组的长度,(alloc - len)表示未使用的空间长度。

如果新增的拼接字符串长度小于未使用空间,就不用扩容了。

2.4 扩容性能较好

Redis字符串还实现空间预分配和惰性空间释放的优化策略,减少扩容次数。

简单理解就是拼接字符串导致扩容的时候会多增加一些空闲空间,缩短字符串的时候并不立即释放这些空闲空间。

我是「一灯架构」,如果本文对你有帮助,欢迎各位小伙伴点赞、评论和关注,感谢各位老铁,我们下期见

内容
  • ***性能优化和调整服务
    ***性能优化和调整服务
    2023-12-31
    ***性能优化和调整服务.***性能优化和调整服务是指针对服务器的硬件和软件进行调整和优化,以提高其运行效率和稳定性的服
  • 科技创新孵化器服务
    科技创新孵化器服务
    2023-12-16
    科技创新孵化器服务.科技创新孵化器是指为初创科技企业提供办公、技术、**和资金服务的机构,而科技创新孵化器服务则是指这些
  • ***迁移与升级解决方案
    ***迁移与升级解决方案
    2024-01-05
    ***迁移与升级解决方案.随着业务的不断扩大和发展,很多企业逐渐意识到原有的***已经不能满足日益增长的需求,因此需要进
  • 虚拟现实技术开发
    虚拟现实技术开发
    2024-01-15
    虚拟现实技术开发.虚拟现实技术已经成为了当今科技行业的热门话题,它的发展日益迅猛,给人们的生活和工作带来了巨大的变革。在
  • 全球电子元件市场趋势分析
    全球电子元件市场趋势分析
    2023-12-31
    全球电子元件市场趋势分析.近年来,全球电子元件市场呈现出不断增长的趋势。随着科技的不断发展和智能设备的普及,电子元件市场
  • 电子元件质量检测与认证服务
    电子元件质量检测与认证服务
    2024-01-05
    电子元件质量检测与认证服务.为什么需要电子元件质量检测与认证服务?.随着电子产业的不断发展,电子元件在各个生产领域都起着
  • ***虚拟化技术咨询服务
    ***虚拟化技术咨询服务
    2023-12-21
    ***虚拟化技术咨询服务.在当今数字化时代,***虚拟化技术越来越受到企业和个人用户的青睐。虚拟化技术通过将物理***划
  • 高性能电子元件**
    高性能电子元件**
    2024-01-10
    高性能电子元件**.随着科技的不断进步,电子行业的发展日新月异。高性能电子元件作为电子产品的关键组成部分,对于产品的性能
  • 定制化电子元件解决方案
    定制化电子元件解决方案
    2024-01-15
    定制化电子元件解决方案.在现代科技发展迅速的时代,电子元件的需求日益增加,同时对于定制化的需求也在不断提升。定制化电子元
  • ***安全加固与防护方案
    ***安全加固与防护方案
    2024-01-10
    ***安全加固与防护方案.随着互联网的快速发展,***安全问题日益凸显。一旦***遭受攻击,可能导致数据泄露、服务中断甚