前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Redis string之SDS源码分析2

Redis string之SDS源码分析2

作者头像
邹志全
发布2019-07-31 15:13:31
3250
发布2019-07-31 15:13:31
举报
文章被收录于专栏:EffectiveCodingEffectiveCoding

上一篇我们看了Redis里面关于新旧版本对于sds的不同的结构体实现,接下来看看sds.c中关于redis动态字符串的具体操作。

从new开始:

sdsnew函数是创建一个sds字符串的开始函数。

image.png

实际的初始化逻辑在sdsnewlen中,不仅是sdsnew函数,sdsempty、sdsup其实内部调的都是sdsnewlen这个函数。

先看一下函数注释的意思,就是说使用给定的字符串长度作为初始化值来创建一个sds动态字符串,如果是Null的话,那就给0字节,最后说了下sds是二进制安全的,我们可以放心的使用\0。

然后是代码逻辑:

1、首先定义了一个void *sh ,这里为了进一步提升性能不同长度的字符串只能使用不同的结构体,所以说无法确切定义 例如:struct sdshdr *sh,这里宏里是写死的。然后声明一个别名(这里的sds其实就是sdshdr中的buf的指针)

2、根据不同的长度决定使用不同的结构体,然后下面那一段是一个经验写法为了放入超过32长度的字符串

3、定义一个具体标示具体结构体的指针

4、剩下的都是根据不同的长度分配对应的结构体,并且设置属性了

image.png

这个函数没有截完整,稍微有点长,后面的都是类似的case 语句啦

除了创建新的字符串,然后就是追加字符串,追加字符串用的是sdscatlen 函数 src/sds.c L:379

这个函数是用于截取指定字符串的指定长度追加到原有字符串中的,sds s:原有串、const void *t:要追加到原有字符串后的值、len:要截取的待拷贝的值的长度

先计算当前字符串已经使用的长度,根据新长度来衡量是进行扩容还是保持不变,直接进行内存拷贝而不是字符串拷贝,来保证二进制兼容,最后设置新长度就好了。

image.png

很显然sdscatlen函数中没有做什么很核心的事儿,真正比较关心其中使用的sdsMakeRoomFor 扩容函数。下面来看一下这个函数:src/sds.c L:197

当出现现有可用空间无法满足新串长度时进行扩容

入参:sds s:带扩容的sds字符串指针、size_t addlen:新串的长度

出参:新的sds指针,如果没发生扩容和入参是一致的

1、首先计算原sds还剩多少可分配空间,如果够的话,直接返回(一直到第8行)

2、如果新长度小于最大预分配长度则扩容为2倍,如果新长度大于最大预分配长度则仅追加SDS_MAX_PREALLOC长度

3、如果是SDS_TYPE_5,则直接分配SDS_TYPE_8类型

4、如果类型没有发生变化则重新开辟一块内存将原先整个SDS拷贝一份过去即可

image.png

其他的另外几个函数都是依赖于这几个核心函数的,现在应该对SDS有了更深一步的理解啦。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019.07.18 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

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