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:> set test ""
OK
127.0.0.1:> object encoding test
"int"
// 插入long的最大值2^63-1
127.0.0.1:> set test ""
OK
127.0.0.1:> object encoding test
"int"
// 插入2^63,就不是int编码了
127.0.0.1:> set test ""
OK
127.0.0.1:> 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:> set test "hello"
    OK
    127.0.0.1:> object encoding test
    "embstr"
    127.0.0.1:> append test "world"
    (integer)
    127.0.0.1:> object encoding test
    "raw"
  • int编码在执行append前,也会先转为raw,再修改
  • int编码执行整数计算时(比如incrby)直接使用整数编码
  • raw和embstr编码,执行整数方法(比如incrby)时,如果其内容为long内的整数,则先转为int再执行,执行完还是int。如果内容不是long内的整数,则向客户端抛出异常

字符串命令详细实现:

redis_字符串对象的更多相关文章

  1. 字符串对象-String

    新建字符串对象 ① 直接赋值 ② 构造函数 ③ 转换函数 1    length              字符串对象属性 2    match()  null     跟php中的preg_matc ...

  2. json对象与json字符串对象格式

    var cStr = "{\"c\":\"{\\\"b\\\":\\\"000\\\",\\\"b2\\\&q ...

  3. js-string字符串对象

    js-string字符串对象 一.String 对象描述 字符串是 JavaScript 的一种基本的数据类型. String 对象的 length 属性声明了该字符串中的字符数. String 类定 ...

  4. 关于Redis中的字符串对象

    一.SDS redis中定义Object types有5种 /* Object types */ #define REDIS_STRING 0 #define REDIS_LIST 1 #define ...

  5. PHP“Cannot use object of type stdClass as array” (php在调用json_decode从字符串对象生成json对象时的报错)

    php再调用json_decode从字符串对象生成json对象时,如果使用[]操作符取数据,会得到下面的错误 错误:Cannot use object of type stdClass as arra ...

  6. [BS-01] 根据字符串对象的参数自动计算用来显示该字符串的UI控件的宽和高

    根据字符串对象的参数自动计算用来显示该字符串的UI控件的宽和高 1.  影响昵称Label的高和宽的因素: 字体和字号大小.文字多少.高度取决于是否固定了宽度(是否限制了最大的宽度和高度) 2. 使用 ...

  7. javascript字符串对象

    String字符串对象 1. 字符串粗体展示: var a = "陈冠希喜欢拍电影";   document.writeln(a.bold()+"<br/>& ...

  8. javascript中的字符串对象和数组对象

    1.javascript的对象的概念 在javascript中,除了null和undefined以处,其他的数据类型都被定义成了对象 也可以用创建对象的方法定义变量,string,math,array ...

  9. json字符串对象内嵌json对象

    有时候需要在json的key:value字符串对象中再嵌入一个json对象,如果需要把如下的json对象作为字符串嵌入到json字符串对象中: { "type": 2, " ...

随机推荐

  1. 关于创建String对象过程的内存分配

    String是引用数据类型 但是String实际上java给我们提供的是一个类 注意:String 全类被fianl所修饰 所以 String 又叫 字符串常量 String 的值 一旦定义 不可以改 ...

  2. 【第二组】Hunter——beta版发布文档

    软件测试报告 一.bug情况汇总 尚需解决以及难以解决的: 登录时会有卡顿,需要加入加载进度条(会添加的) 商城和背包功能尚未实现(需要修复) 美工水平太差,让人没有使用的欲望(大概接下来就专门做这个 ...

  3. ARTS打卡计划第一周-Algorithm

    7. Reverse Integer import math class Solution: def reverse(self, x: int) -> int: ret = 0 if x > ...

  4. P61 实践作业

    网络攻防实验环境搭建 根据链接下载的实验工具包,将其解压 打开VM虚拟机,点击图中红色框,扫描虚拟机 选择文件所在位置 点击下一步,完成.即可 在VM虚拟机设置中把网络适配器修改为桥接模式.如下图 在 ...

  5. 微信小程序——编辑

    记录一下 微信小程序分页编辑,可增页删除当前页面.第一页为主图片和主句子.其他页面一致. 左滑右滑可切换页面.每页可增加0到1页.小黑点与页面一致. /* pages/booktool/write/w ...

  6. 桥接模式和nat模式的区别

    桥接模式:VMware虚拟的系统就想局域网中独立的主机一样(有独立的IP)它可以访问网内任何一台机器 Nat模式:可以通过宿主机访问互联网(宿主机联网,虚拟机就能联网)它不能和本局域网中的其他主机进行 ...

  7. Linux服务器文件和windows本机文件互传方法(本地文件上传Linux,Linux文件下载到本机)

    1.windows系统中下载XShell安装文件.下载地址:https://www.newasp.net/soft/384562.html 2.安装之后,新建会话输入远程linux的账号和密码. 3. ...

  8. docker image 详解

    docker iamge docker 镜像: [root@localhost ~]# docker image --help Usage: docker image COMMAND 管理镜像 Com ...

  9. maven项目引用时,导入类报错,选择两个项目同时执行Maven update

    maven项目引用时,导入类报错,选择两个项目同时执行Maven update springboot引入第三方jar,需要扫描时加@ComponentScan("第三方的包名") ...

  10. 5个数组Array方法: indexOf、filter、forEach、map、reduce使用实例

    ES5中,一共有9个Array方法 Array.prototype.indexOf Array.prototype.lastIndexOf Array.prototype.every Array.pr ...