Redis数据类型-String总结

Redis是工作中使用比较多的中间件,它支持丰富的数据结构,拥有极强的读写性能,tps可以达到10w+。

今天这篇文章来分析和总结String类型也是使用最多的一种数据结构之一。本文是基于redis5.0进行分析。

 

一、基本使用

set key value [EX seconds] [PX milliseconds] [NX|XX]       

1、set是语法,key是指定名称, value是需要存储的值

2、EX 指定过期的秒时间,PX指定过期的毫秒时间

3、NX:只有key不存在的时候,才设置成功

4、XX:只有key存在的时候,才设置成功

总结:5.0支持set命令指定过期时间和不存在的时候才设置成功,也就是通过一条命令就可以实现分布式锁加锁的功能,以前的版本设置key和设置过期时间需要分成两个命令,原子性保证难度更大。

 

二、使用场景

1、热点数据缓存,分布式session

2、Setnx `分布式锁`

3、incr 计数器

4、Incr 全局id

5、`Incr 限流`

6、bit 操作,位图功能,在线用户统计 0/1标记 

 

三、支持存储的数据类型

整型,字符型,float(单浮点型) 

 

四、类型都是string,但是编码不一样

五、String存储原理

在Redis中,数据存储在一个RedisObject类中

typedef struct redisObject {    //这个类型可以是string,也可以是hash,zset等等    unsigned type:4;    unsigned encoding:4;    //记录lru,lfu淘汰算法依赖的访问时间和访问频率    unsigned lru:LRU_BITS; /* LRU time (relative to global lru_clock) or                            * LFU data (least significant 8 bits frequency                            * and most significant 16 bits access time). */    //引用计数器    int refcount;    //指向真实数据结构对象    void *ptr;} robj;

对于String,Redis自定义了一种简单动态字符串的数据结构来存储字符串数。

源码实现:多种数据结构,分别表示可以存储不同长度的字符串。

len:代表已经使用的长度

alloc:分配的总内存大小

flags:代表存储类型

buf[]:实际的数据

 

六、三种编码存储区别

1、embstr的RedisObject,SDS内存在一块,只要创建时`分配一次内存`,销毁时`释放一次内存`,查找方便

2、raw则RedisObject,SDS内存不在一块,需要创建时`分配两次内存`,销毁时`释放两次内存`

3、embstr的结构,决定了他需要增加长度时,RedisObject,SDS都需要重新分配内存。因此`embstr编码的数据是不能修改的,只读的`。 

 

 

七、 int,embstr编码什么时候转换成raw

1、int类型的数据不再是int类型,转成raw

2、长度大于2^63-1转成embstr

3、embstr字符超过44字节,转成raw 

 

八、SDS数据结构的优点

1、`二进制安全的` 可以存储图片 整形,浮点型

2、String 的三种编码,充分利用内存,提高内存利用率

  • `int` 存储8个字节长整形 long ,2^63-1

  • `Embstr` embstr格式的SDS simple Dynamic String 内存空间是连续的,只读的,只要执行修改就会转成raw

  •  `Raw`,SDS,存储大于44个字节的字符串

3、`不用担心内存溢出,sds具备自动扩容能力`

4、`获取字符串长度时间复杂度O(1)`,存储了len属性

5、通过`空间预分配`和`惰性空间释放`防止多次分配内存

6、判断是否结束使用len属性,可以包含'\0',操作字符串。 

 

九、为什么不用c中的字符数组,有哪些问题?

1、需要预先分配内存,可能`内存溢出`

2、获取长度需要遍历数组,`时间复杂度O(n)`

3、字符数组长度变化,需要`内存重分配`

4、c的字符数组中,'\0'代表判断结束。`二进制数据存储不安全`,不能保存图片,视频等。 

 

十、关于内存预分配特性

通过源码分析,扩容策略是字符串在长度小于 SDS_MAX_PREALLOC 之前,扩容空间采用加倍策略,也就是保留 100% 的冗余空间。当长度超过 SDS_MAX_PREALLOC 之后,为了避免加倍后的冗余空间过大而导致浪费,每次扩容只会多分配 SDS_MAX_PREALLOC大小的冗余空间。 

 

十一、关于惰性空间释放

惰性空间释放用于优化 SDS 的字符串缩短操作:当 SDS 的 API 需要缩短 SDS 保存的字符串时, 程序并不立即使用内存重分配来回收缩短后多出来的字节, 而是使用 free 属性将这些字节的数量记录起来,并等待将来使用。 

//仅仅设置长度,没有真正清除数据void sdsclear(sds s) {    //单纯设置长度为0    sdssetlen(s, 0);    //第一个字符设置为结束符    s[0] = '\0';}

//真正的清除空间

sds sdsRemoveFreeSpace(sds s) {    struct sdshdr *sh;    sh = (void*) (s-(sizeof(struct sdshdr)));    // 进行内存重分配,让 buf 的长度仅仅足够保存字符串内容    // T = O(N)    sh = zrealloc(sh, sizeof(struct sdshdr)+sh->len+1);    // 空余空间为 0    sh->free = 0;    return sh->buf;}


以上便是关于string的知识点记录,string的设计很多地方都非常巧妙,比如不同的结构体存储不同长度的字符串,不同编码类型存储不同长度的字符串,

空间预分配,空间惰性释放等,从存储结构,编码类型,内存分配策略和回收策略,作者都从性能方面做了非常多的考量设计,可想而知这也是redis为什么性能极高的原因,工作中也要学习这种追求极致性能的优良风格和设计风格。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

服务端技术栈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值