redis_字符串对象
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_字符串对象的更多相关文章
- 字符串对象-String
新建字符串对象 ① 直接赋值 ② 构造函数 ③ 转换函数 1 length 字符串对象属性 2 match() null 跟php中的preg_matc ...
- json对象与json字符串对象格式
var cStr = "{\"c\":\"{\\\"b\\\":\\\"000\\\",\\\"b2\\\&q ...
- js-string字符串对象
js-string字符串对象 一.String 对象描述 字符串是 JavaScript 的一种基本的数据类型. String 对象的 length 属性声明了该字符串中的字符数. String 类定 ...
- 关于Redis中的字符串对象
一.SDS redis中定义Object types有5种 /* Object types */ #define REDIS_STRING 0 #define REDIS_LIST 1 #define ...
- 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 ...
- [BS-01] 根据字符串对象的参数自动计算用来显示该字符串的UI控件的宽和高
根据字符串对象的参数自动计算用来显示该字符串的UI控件的宽和高 1. 影响昵称Label的高和宽的因素: 字体和字号大小.文字多少.高度取决于是否固定了宽度(是否限制了最大的宽度和高度) 2. 使用 ...
- javascript字符串对象
String字符串对象 1. 字符串粗体展示: var a = "陈冠希喜欢拍电影"; document.writeln(a.bold()+"<br/>& ...
- javascript中的字符串对象和数组对象
1.javascript的对象的概念 在javascript中,除了null和undefined以处,其他的数据类型都被定义成了对象 也可以用创建对象的方法定义变量,string,math,array ...
- json字符串对象内嵌json对象
有时候需要在json的key:value字符串对象中再嵌入一个json对象,如果需要把如下的json对象作为字符串嵌入到json字符串对象中: { "type": 2, " ...
随机推荐
- jquery中checkbox的选中,反选,全不选 注意1.6版本以上将attr改成prop
<script type="text/javascript"> $(function () { // 全选 $("#btnCheckAll").bi ...
- CSS 图像左右对齐
左右对齐图像使用的技术是浮动div元素. float:left 左对齐 float:right右对齐 示例 <!DOCTYPE html> <html> <hea ...
- 在anaconda下安装已经下载好Opencv4的痛苦回忆
来来回回装了很多回,今天终于一鼓作气把它安装好,记录一下过程. 准备: Opencv4的安装包,可以在官网上下载 anaconda——主要目的是在anaconda下的某个environment中安装最 ...
- wsl ubuntu 配置c++环境
1.sudo apt-get install build-essential 更新 配置源 2.sudo apt install gcc-8 3.sudo apt install g++-8 cd ...
- java中的数据导出到Excel表中
整个项目中导出数据到.Excel的源码 import java.io.BufferedOutputStream; import java.io.FileInputStream; import java ...
- Failed to execute goal org.apache.maven.plugins:maven-clean-plugin:2.4.1:clean (default-clean) on project
在maven项目中 启动了2个tomcat,只能启动一个.
- Linux nfs使用krb5的方式安全挂载
配置安全的网络nfs文件共享服务 由于本人是使用的rhce模拟考试环境来做的本题目,所以文中说到的实验脚本和评分脚本,以及krb5.keytab文件只有我本套环境独有,如果自己做练习可以不去使用实验脚 ...
- Linux服务器文件和windows本机文件互传方法(本地文件上传Linux,Linux文件下载到本机)
1.windows系统中下载XShell安装文件.下载地址:https://www.newasp.net/soft/384562.html 2.安装之后,新建会话输入远程linux的账号和密码. 3. ...
- 记一次git翻车事件
昨天dmp上线了 本来整个流程是 1.在本地1.4分支开发,开发完成push到origin/1.4,在远程仓库把1.4 merge到master分支 2.本地online分支先pull一下远程onli ...
- 随机获得id的方法
public String generateUUID() { String uuid = UUID.randomUUID().toString(); uuid = uuid.replace(" ...