为了账号安全,请及时绑定邮箱和手机立即绑定

redis_字符串对象

标签:
Java SpringBoot

Redis总共支持五种数据类型:string,hash,list,set及zset。这里介绍字符串类型的实现

 

首先了解字符串对象的结构

?

// redis对象内存分配,列出主要相关的属性redisObject {    // 对于字符串对象,type = REDIS_STRING    type    // 字符串的底层编码,有三种:int、raw、embstr,后文介绍    encoding    // 指向实际保存字符串内容的空间    ptr    // 还有其他属性    ......}

上面的redisObject不实际保存字符串内容,而是通过ptr指向实际保存字符串内容的空间,叫sdshdr(Simple Dynamic String hdr 简单动态字符串)

?


struct sdshdr {    // 记录buf数组中已使用的字节数,等同于字符串长度(不包括结尾的\0)    int len;    // 记录buf数组中未使用的字节数    int free;    // 实际保存字符串的字节数组    char buf[];}

这个sdshdr比较厉害,在字符串变长的时候可以预申请额外内存、缩短时不直接释放内存以备未来变长使用,等。

sdshdr的详细看这里:https://www.cnblogs.com/loveCheery/p/9133343.html

 

字符串编码

字符串对象有三种可能的底层编码:int、raw、embstr。

这三种编码格式是字符串对象底层空间分配的不同,对上层调用没有区别,不同编码的字符串对象在执行命令时效果是一样的

int编码

如果字符串保存的值是整数,范围在long之内,那么encoding会被设置为int,并且直接将证书值保存在ptr里(ptr不再指向一个复杂的sds结构了,直接是整数值)

复制代码

// 插入long之内的值为整数的字符串127.0.0.1:6379> set test "123" OK127.0.0.1:6379> object encoding test"int"// 插入long的最大值2^63-1127.0.0.1:6379> set test "9223372036854775807" OK127.0.0.1:6379> object encoding test"int"// 插入2^63,就不是int编码了127.0.0.1:6379> set test "9223372036854775808" OK127.0.0.1:6379> object encoding test"embstr"

复制代码

raw编码

如果字符串保存的值长度比较大,那么encoding为raw,值使用sds(简单动态字符串),ptr指向这个sds的空间

比较大:《Redis设计与实现》里说长度大于39字节时,n多文章说长度大于32字节时,我测试返回长度大于44时才行,没查到是配置可选的还是redis版本指定的

总的来说就是对于大字符串,redis采用一套机制来控制字符串变长变短时的内存分配策略,实现是用的sds

embstr编码

如果字符串保存的值不是整数,并且长度不是很大,那么encoding为embstr,值也是sds,ptr指向这个sds的空间

embstr编码是专门用于保存段字符串的一种优化编码方式

  • embstr和raw的实际字符串存储都是用了sds,区别在于:

  • embstr编码的字符串对象,其所有数据保存在一块连续的内存空间中(redisObject和其ptr指向的sds在连续的内存空间),只需要一次内存分配操作

  • raw编码的字符串对象,redisObject和其ptr指向的sds是不连续的,需要两次内存分配

embstr的内存空间连续的优势

  • 其创建时的内存分配、释放时的内存回收次数都只有1次

  • 方便预读取一段空间内的数据做缓存

其他

  • embstr只读,没有修改方法。当对embstr编码的字符串做修改时,会先转为raw、再修改

  • 复制代码

    127.0.0.1:6379> set test "hello"OK127.0.0.1:6379> object encoding test"embstr"127.0.0.1:6379> append test "world"(integer) 10127.0.0.1:6379> object encoding test"raw"

    复制代码

  • int编码在执行append前,也会先转为raw,再修改

  • int编码执行整数计算时(比如incrby)直接使用整数编码

  • raw和embstr编码,执行整数方法(比如incrby)时,如果其内容为long内的整数,则先转为int再执行,执行完还是int。如果内容不是long内的整数,则向客户端抛出异常

字符串命令详细实现:

 https://img1.sycdn.imooc.com//5b17d1be00010f0110801078.jpg

 

micheal.li > 李智 18844195846
micheal.li > iQIYI PICTURES DEV
micheal.li > mikeve@163.com

原文出处

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消