redis数据结构底层复习之String在redis底层的存储

Redis使用SDS而非C语言字符串作为动态字符串,SDS提供了长度信息避免遍历计算,预防缓冲区溢出,减少内存重分配,并支持二进制安全性,适合处理包括二进制数据在内的各种字符串操作。
摘要由CSDN通过智能技术生成

前言
先来回忆一下redis的基本数据类型:

String, List, set, zSet, hash

顺便想想这些问题:String在Redis底层是怎么存储的?这些数据类型在Redis中是怎么存放的?Redis快的原因就只有单线程和基于内存么?

今天先复习String在redis底层的存储

String在redis底层如何存储

redis是C语言开发的,但是没直接采用c语言的字符串类型,而是自己构建了 动态字符串(SDS) 的抽象类型

struct sdshdr{
 int len;//字符串长度
 int free;//未使用长度
 char buf[];//字符数组
}

SDS在redis中除了用作字符串,还用作缓冲区(buffer).
在这里插入图片描述
两个SDS,一个是名为aobing的Key SDS,另一个是名为cool的Value SDS.

在这里插入图片描述

SDS与字符串的区别

1.1 计数方式不同

C语言对于字符串的统计,完全来自遍历,从头遍历到末尾,知道发现空字符串就停止,这样统计出来的字符串长度时间复杂度为O(n)
在这里插入图片描述
SDS会保留长度信息,免去每次遍历获取字符串长度。所以redis速度提升了

1.2 杜绝缓冲区溢出

字符串拼接的时候,由于c语言没有记录字符串长度,没有提前计算好内存,调用拼接函数的时候可能会产生缓存区溢出。

SDS根据free判断是否可以存放拼接的字符串,如果不够进行扩容。

1.3 减少修改字符串时带来的内存重分配字数

C语言字符串底层也是数组,每次创建的时候就创建长度为N+1的字符,多的1是为了保存空字符’\0’。

SDS不对空字符串进行判断,只需判断len和free

Redis是个高速缓存数据库,如果频繁对字符串进行拼接和截断,很容易造成缓冲区溢出和内存泄露。内存分配算法很耗时开销很大。

Redis为了避免C字符串这样的缺陷,就分别采用了两种解决方案,去达到性能最大化,空间利用最大化:

  • 空间预分配:当我们对SDS进行扩展操作的时候,Redis会为SDS分配好内存,并且根据特定的公式,分配多余的free空间,还有多余的1byte空间(这1byte也是为了存空字符),这样就可以避免我们连续执行字符串添加所带来的内存分配消耗。
  • 惰性空间释放:刚才提到了会预分配多余的空间,很多小伙伴会担心带来内存的泄露或者浪费,别担心,Redis大佬一样帮我们想到了,当我们执行完一个字符串缩减的操作,redis并不会马上收回我们的空间,因为可以预防你继续添加的操作,这样可以减少分配空间带来的消耗,但是当你再次操作还是没用到多余空间的时候,Redis也还是会收回对于的空间,防止内存的浪费的。

1.4 二进制安全

C语言根据空字符串判断字符长度,但是图片,音频,视频,压缩文件的二进制文件会穿插空字符串在中间。

Redis由于保存了字符串的长度, 避免判断空字符,直接判断长度,所以redis也经常被我们拿来保存各种二进制数据。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值