简单动态字符串的理解?

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: 《基础》

Redis中的简单动态字符串其实是对C语言中的字符串的封装和优化,

因为C语言的字符串有两个缺点:

1.不是二进制安全的(因为字符串以空字符作为结束的标志,字符串中间不能有空字符,Redis的简单动态字符串是一个结构体,有一个变量存储了字符串的长度,所以不需要以空字符作为结束的标志)。

从定义上来看,二进制安全是一种主要用于字符串操作函数相关的计算机编程术语。一个二进制安全功能(函数),其本质上将操作输入作为原始的、无任何特殊格式意义的数据流。对于每个字符都公平对待,不特殊处理某一个字符。

简单来说C语言使用\0字符来作为字符串结束符是不符合这种二进制安全的规范的。

2.频繁修改一个字符串时,会涉及到内存的重分配,比较消耗性能。(Redis中的简单动态字符串会有内存预分配和惰性空间释放)。

如果字符串实际使用长度len<1M,实际分配空间=len长度来存储字符串+1字节存末尾空字符+len长度的预分配空闲内存

如果字符串实际使用长度len>1M,实际分配空间=len长度来存储字符串+1字节存末尾空字符+1M长度的预分配空闲内存

所以Redis中的简单动态字符串结构,除了包含一个字符数组的属性,还包含数组的长度,数组的实际使用长度等属性,通过增加长度属性,可以保证字符串是二进制安全的,从而可以保存任意类型的数据,例如一张图片,对象序列化后的数据等等。

字符串使用场景如下:

1.字符串可以保存一些字符串数据,也可以保存一些数字类型的数据,所以可以使用INCR, DECR, INCRBY对数字进行加减,所以可以把字符串当成计数器使用。

2.同时因为在C语言中,每个字符是一个字节,是8个二进制位,所以可以把简单动态字符串作为一个位数组来使用,通过setbit,getbit命令来对位数组进行赋值,取值,可以以很小的空间来保存用户一年的每日签到数据,以及Redis中的布隆过滤器也是通过位数组来实现的。

字符串的底层存储

在Redis中,每一个Value都是一个Redis对象,对应的都是RedisObject结构,在RedisObject结构中,保存了对象的类型type,底层的编码encoding等一些属性,也拥有一个ptr指针,指向对象具体的存储地址。

struct RedisObject {
    int4 type; //类型
    int4 encoding; //编码
    int24 lru; 
    int32 refcount; 
    void *ptr; 
} robj;点击复制代码复制出错复制成功

在Redis中,字符串有两种存储方式,int编码,embstr编码和raw编码。

int编码

当value是一个整数,并且可以使用long类型(8字节)来表示时,那么会属于int编码,ptr直接存储数值。(并且Redis会进行优化,启动时创建0~9999的字符串对象作为共享变量。)

embstr和raw编码

两种存储方式下,都RedisObject和SDS结构(简单动态字符串)来存储字符串,区别在于,embstr对象用于存储较短的字符串,embstr编码中RedisObject结构与ptr指向的SDS结构在内存中是连续的,内存分配次数和内存释放次数均是一次,而raw编码会分别调用两次内存分配函数来分别创建RedisObject结构和SDS结构。

相关实践学习
基于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
相关文章
|
5月前
|
C++
【C++基础】C++中的字符串
【C++基础】C++中的字符串
19 0
C++11 可变模板参数
C++11 可变模板参数
49 0
|
5月前
|
JavaScript 前端开发 Java
字符串的引用方式
字符串的引用方式
110 0
|
10月前
|
算法 测试技术 C#
C++算法:包含三个字符串的最短字符串
C++算法:包含三个字符串的最短字符串
字符串的转化规则?
null和 undefined类型 ,null 转换为 “null”,undefined 转换为 “undefined”,
|
JavaScript 前端开发
javascript:将数组转为字符串通过判断包含字段进行状态判断的解决方案
javascript:将数组转为字符串通过判断包含字段进行状态判断的解决方案
49 0
|
JavaScript 前端开发
javascript封装函数:substr函数实现自动截取长度超出限制字数的解决方案
javascript封装函数:substr函数实现自动截取长度超出限制字数的解决方案
95 0
|
网络架构 索引
ES6新增扩展:字符串-数值-数组-函数-对象
ES6新增扩展:字符串-数值-数组-函数-对象
84 0
|
索引
查询字符串 & 模板字符串
查询字符串 & 模板字符串