Redis之字符串

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: Redis之字符串

字符串

C语言中的字符串标准形式是以NULL(十六进制的 0x\0) 作为结束符,如果要获取字符串的长度需要使用strlen标准库函数,该函数算法复杂度是O(n),需要对整个字符串进行遍历,Redis无法承受这么慢的速度,

因此Redis中的字符串在内存中是以字节数组的形式存在,叫做SDS (Simple Dynamic String),是一个带着长度信息的字节数组。

struct SDS<T> {
    T capacity; // 数组容量
    T len; // 数组长度
    byte flags; // 特殊标志位
    byte[] content; // 数组内容
}

SDS的结构很像Java中的ArrayList,content数组中存储着真实的内容,但是这个数组一般会比内容的实际长度要多一些冗余空间,

capacity表示数组的长度,len表示真实的字符串长度,因为字符串在redis中是可修改的,需要支持append操作,

如果数组没有冗余空间,append的时候就必须重新开辟一个新数组,然后将老数组中的内容复制过去,这是一个比较大的开销。

image.png

SDS中使用了泛型T,而不是直接使用int,因为当字符串比较短的时候,len和capacity可以通过byte和short表示,以此达到节省空间的作用,所以不同长度的字符串会用不同的结构体表示。

追加字符串的代码:


sds sdscatlen(sds s, const void *t, size_t len) {
    // 原字符串长度
    size_t curlen = sdslen(s);
    // 按需调整空间,如果capacity不够容纳追加的内容,就会重新分配字节数组,并将原字符串中的内容复制到新数组中
    s = sdsMakeRoomFor(s,len);
    // 内存不足
    if (s == NULL) return NULL;
    // 追加目标字符串的内容到字节数组中
    memcpy(s+curlen, t, len);
    // 设置追加后的长度值
    sdssetlen(s, curlen+len);
    // 让字符串以\0结尾
    s[curlen+len] = '\0';
    return s;
}

Redis规定字符串长度最大不能超过512MB,创建字符串时 len 和 capacity 是一样长的,不会分配冗余空间,因为大多数情况下,不会用到字符串的append。

embstr 与 raw

Redis字符串有两种存储方式,长度很短时,使用 embstr 形式存储,字节长度超过44时,使用raw形式存储。

44个字符:

127.0.0.1:6379> set hello abcdefghijklmnopqrstuvwxyz012345678912345678

OK

127.0.0.1:6379> debug object hello

Value at:0xffff9f531e40 refcount:1 encoding:embstr serializedlength:45 lru:14436129 lru_seconds_idle:5

45个字符:

127.0.0.1:6379> set hello abcdefghijklmnopqrstuvwxyz0123456789123456789

OK

127.0.0.1:6379> debug object hello

Value at:0xffff9f18d2e0 refcount:1 encoding:raw serializedlength:46 lru:14436171 lru_seconds_idle:2

上面两端内容中,encoding表示存储形式,可以看到44个字节是embstr,45个就是raw了。

对象头

Redis每个对象都有一个头结构:

struct RedisObject { 
    int4 type ;         // 4bits
    int4 encoding ;     // 4bits
    int24 lru ;         // 24bits
    int32 refcount ;    // 4bytes 
    void *ptr;          // 8bytes 
} robj ;

每个对象都有类型type、存储形式encoding,以及对象的lru信息,

还有refcount,代表对象的引用计数,为0时对象被销毁回收,ptr指针指向对象内容(body)的具体存储位置,

对象头将占用16字节的存储空间。

在字符串内容较小时,SDS结构体的内存占用空间情况如下:

struct SDS {
    int8 capacity; //1byte
    int8 len; //1byte
    int8 flags; //1byte
    byte[] content; //内容数组,长度为capacity
}

也就是说SDS对象头结构的16字节再加上SDS结构中的3个字节,意味着一个字符串至少占用19个字节,

embstr在内存中存储时,位置与对象头在一起,使用malloc方法一次性分配对象头+对象的空间,而raw不是,需要进行两次malloc分配,对象头和内容在内存上不是连续的。

image.png

因为内存分配器jemalloc、tcmalloc分配内存大小的单位都是2/4/8/16/32/64字节,为了容纳一个embstr的字符串,jemalloc一般会分配32个字节,如果字符串更长一些就是64个字节,

如果字符串总体超过64个字节的时候,Redis认为其不适合使用embstr形式存储,该使用raw了。

因为Redis对象头就占用了16个字节,再加上3个属性的总和3字节,还剩 64 - 19 = 45 个字节,字符串需要用NULL结尾,NULL又占了一个字节,所有最终只剩下44个字节用于存字符串的内容了,这就是上面看到的超过44个字节encoding就变成了raw的原因。

image.png

扩容策略

在字符串小于1MB前,拓容空间将直接翻倍,超过后,为了避免浪费,每次拓容仅追加1MB的冗余空间。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
16天前
|
XML JSON NoSQL
Redis的常用数据结构之字符串类型
Redis的常用数据结构之字符串类型
19 0
|
1月前
|
NoSQL 安全 Linux
Redis 字符串:SDS
Redis 字符串:SDS
37 0
|
2月前
|
存储 NoSQL 5G
redis优化编码之字符串
Redis数据结构之字符串
41 2
redis优化编码之字符串
|
1天前
|
存储 NoSQL 安全
Redis入门到通关之数据结构解析-动态字符串SDS
Redis入门到通关之数据结构解析-动态字符串SDS
|
23天前
|
存储 消息中间件 缓存
Redis 字符串:用一串数据解决多种问题
Redis 字符串:用一串数据解决多种问题
|
3月前
|
存储 消息中间件 缓存
Redis不止能存储字符串,还有List、Set、Hash、Zset,用对了能给你带来哪些优势?
Redis不止能存储字符串,还有List、Set、Hash、Zset,用对了能给你带来哪些优势?
|
4月前
|
NoSQL Unix Redis
①Redis String 字符串类型【命令汇总】
①Redis String 字符串类型【命令汇总】
41 0
|
4月前
|
存储 NoSQL 安全
Redis | 源码阅读 —— 字符串
Redis | 源码阅读 —— 字符串
31 0
|
4月前
|
存储 NoSQL Redis
Redis | Redis 字符串相关命令
Redis | Redis 字符串相关命令
44 0
|
5月前
|
NoSQL 安全 API
redis6.0源码分析:简单动态字符串sds
redis6.0源码分析:简单动态字符串sds
36 0
redis6.0源码分析:简单动态字符串sds

热门文章

最新文章