Redis 设计与实现读书笔记一 Redis字符串
1 Redis 是C语言实现的
2 C字符串是 /0 结束的字符数组
3 Redis具体的动态字符串实现
- /*
- * 保存字符串对象的结构
- */
- struct sdshdr {
- // buf 中已占用空间的长度 使求字符串长度操作变成0(1)
- int len;
- // buf 中剩余可用空间的长度 对字符串字符增加修改时 不大于len+free不用重新分配内存(初始化一个字符串时free为0 当修改字符串时会对free进行赋值)
- int free;
- // 数据空间
- char buf[];
- };
sdshdr |
free 5 |
len 5 |
buf |
--->
'R' | 'e' | 'd' | 'i' | 's' | '/0' |
4 感觉更像 Java 中的 StringBuffer 的设计
5 源码初始化一个字符串
- /*
- * 根据给定的初始化字符串 init 和字符串长度 initlen
- * 创建一个新的 sds
- *
- * 参数
- * init :初始化字符串指针
- * initlen :初始化字符串的长度
- *
- * 返回值
- * sds :创建成功返回 sdshdr 相对应的 sds
- * 创建失败返回 NULL
- *
- * 复杂度
- * T = O(N)
- */
- /* Create a new sds string with the content specified by the 'init' pointer
- * and 'initlen'.
- * If NULL is used for 'init' the string is initialized with zero bytes.
- *
- * The string is always null-termined (all the sds strings are, always) so
- * even if you create an sds string with:
- *
- * mystring = sdsnewlen("abc",3");
- *
- * You can print the string with printf() as there is an implicit \0 at the
- * end of the string. However the string is binary safe and can contain
- * \0 characters in the middle, as the length is stored in the sds header. */
- sds sdsnewlen(const void *init, size_t initlen) {
- struct sdshdr *sh;
- // 根据是否有初始化内容,选择适当的内存分配方式
- // T = O(N)
- if (init) {
- // zmalloc 不初始化所分配的内存
- sh = zmalloc(sizeof(struct sdshdr)+initlen+);
- } else {
- // zcalloc 将分配的内存全部初始化为 0
- sh = zcalloc(sizeof(struct sdshdr)+initlen+);
- }
- // 内存分配失败,返回
- if (sh == NULL) return NULL;
- // 设置初始化长度
- sh->len = initlen;
- // 新 sds 不预留任何空间
- sh->free = ;
- // 如果有指定初始化内容,将它们复制到 sdshdr 的 buf 中
- // T = O(N)
- if (initlen && init)
- memcpy(sh->buf, init, initlen);
- // 以 \0 结尾
- sh->buf[initlen] = '\0';
- // 返回 buf 部分,而不是整个 sdshdr
- return (char*)sh->buf;
- }
6 修改字符串之前对free操作
- /*
- * 在不释放 SDS 的字符串空间的情况下,
- * 重置 SDS 所保存的字符串为空字符串。
- *
- * 复杂度
- * T = O(1)
- */
- /* Modify an sds string on-place to make it empty (zero length).
- * However all the existing buffer is not discarded but set as free space
- * so that next append operations will not require allocations up to the
- * number of bytes previously available. */
- void sdsclear(sds s) {
- // 取出 sdshdr
- struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
- // 重新计算属性
- sh->free += sh->len;
- sh->len = ;
- // 将结束符放到最前面(相当于惰性地删除 buf 中的内容)
- sh->buf[] = '\0';
- }
- /* Enlarge the free space at the end of the sds string so that the caller
- * is sure that after calling this function can overwrite up to addlen
- * bytes after the end of the string, plus one more byte for nul term.
- *
- * Note: this does not change the *length* of the sds string as returned
- * by sdslen(), but only the free buffer space we have. */
- /*
- * 对 sds 中 buf 的长度进行扩展,确保在函数执行之后,
- * buf 至少会有 addlen + 1 长度的空余空间
- * (额外的 1 字节是为 \0 准备的)
- *
- * 返回值
- * sds :扩展成功返回扩展后的 sds
- * 扩展失败返回 NULL
- *
- * 复杂度
- * T = O(N)
- */
- sds sdsMakeRoomFor(sds s, size_t addlen) {
- struct sdshdr *sh, *newsh;
- // 获取 s 目前的空余空间长度
- size_t free = sdsavail(s);
- size_t len, newlen;
- // s 目前的空余空间已经足够,无须再进行扩展,直接返回
- if (free >= addlen) return s;
- // 获取 s 目前已占用空间的长度
- len = sdslen(s);
- sh = (void*) (s-(sizeof(struct sdshdr)));
- // s 最少需要的长度
- newlen = (len+addlen);
- // 根据新长度,为 s 分配新空间所需的大小
- if (newlen < SDS_MAX_PREALLOC)
- // 如果新长度小于 SDS_MAX_PREALLOC
- // 那么为它分配两倍于所需长度的空间
- newlen *= ;
- else
- // 否则,分配长度为目前长度加上 SDS_MAX_PREALLOC
- newlen += SDS_MAX_PREALLOC;
- // T = O(N)
- newsh = zrealloc(sh, sizeof(struct sdshdr)+newlen+);
- // 内存不足,分配失败,返回
- if (newsh == NULL) return NULL;
- // 更新 sds 的空余长度
- newsh->free = newlen - len;
- // 返回 sds
- return newsh->buf;
- }
Redis 设计与实现读书笔记一 Redis字符串的更多相关文章
- Redis设计与实现读书笔记——简单动态字符串
前言 项目里用到了redis数据结构,不想只是简单的调用api,这里对我的读书笔记做一下记录.原文地址: http://www.redisbook.com/en/latest/internal-dat ...
- Redis 设计与实现读书笔记一 Redis List
list结构体 adlist.h/list(源码位置) /* * 双端链表结构 */ typedef struct list { // 表头节点 listNode *head; // 表尾节点 lis ...
- Redis设计与实现读书笔记(二) 链表
链表作为最基础的数据结构,在许多高级语言上已经有了很好的实现.由于redis采用C语言编写,需要自己实现链表,于是redis在adlist.h定义了链表类型.作者对于这部分没什么好说,源码比较简单,如 ...
- Redis设计与实现读书笔记(一) SDS
作为redis最基础的底层数据结构之一,SDS提供了许多C风格字符串所不具备的功能,为之后redis内存管理提供了许多方便.它们分别是: 二进制安全 减少字符串长度获取时间复杂度 杜绝字符串溢出 减少 ...
- <<redis设计和实现>>读书笔记
redis如何实现主从同步的高效率?? 主从复制的同步有一个命令数据的同步文本,然后利用两个不同服务器的偏移量来进行进行同步,避免每次都是全部同步(并非会保存所有的命令数据,而是会有一个缓冲区(比如1 ...
- Redis设计与实现读书笔记——双链表
前言 首先,贴一下参考链接: http://www.redisbook.com/en/latest/internal-datastruct/adlist.html, 另外真赞文章的作者,一个90后的小 ...
- Linux内核设计与实现 读书笔记 转
Linux内核设计与实现 读书笔记: http://www.cnblogs.com/wang_yb/tag/linux-kernel/ <深入理解LINUX内存管理> http://bl ...
- 【2018.08.13 C与C++基础】C++语言的设计与演化读书笔记
先占坑 老实说看这本书的时候,有很多地方都很迷糊,但却说不清楚问题到底在哪里,只能和Effective C++联系起来,更深层次的东西就想不到了. 链接: https://blog.csdn.net/ ...
- 【读书笔记】Redis入门
1:Redis概览 Remote Dictionary Server 远程字典服务 Redis是基于内存的存储 在一台普通的笔记本上,Redis每秒的读取速度可以达到10万 内存读取数据,断电的时候数 ...
随机推荐
- jar转dll
IKVM http://www.cnblogs.com/luckeryin/archive/2012/03/28/2421274.html
- Steam和Byte[]之间进行输换
一. 二进制转换成图片 MemoryStream ms = new MemoryStream(bytes); ms.Position = 0; Image img = Image.FromStream ...
- JDE910笔记2--OMW项目建立及简单使用[转]
1.打开JDE的OBJECT MANAGEMENT WORKBENCH.在工作区中选择ADD,建立项目并选择OMW PROJECT,添加相关信息,如下图所示 其中,ProjectID可以对应不同的数据 ...
- LoadRunner 文本检查点使用
在测试时,我们可以根据文本检查点判断事务是否执行正确. 我们在启动流程时,成功返回: 我们检查这个响应结果是否有. int i=0; i=web_reg_find("Text=\&q ...
- HTTP 错误 500.22 - Internal Server Error 检测到在集成的托管管道模式下不适用的 ASP.NET 设置
答案:在将WebDataHelper升级到VS2013是出现的这个错误,这个程序使用了URL重写的技术, 解决方法是:需要将重写的配置,迁移到system.webServer配置节中
- C#入门篇6-9:字符串操作 不值一提的函数【不看也行】
// 判断输入的是否全是数字:返回结果:true:全是数字:false:有字幕出现 public static bool Isaccord1(string str) { bool bl = true; ...
- 在ASP.NET MVC中使用CKEditor和CkFinder
在你需要使用editor控件的页面头部添加: <head> ... <script type="text/javascript" src="/ckedi ...
- 构建之法<第四章>之感悟
第四章:两人合作内容出处:4.6 两人合作的不同阶段和技巧 本章主要是讲关于合作方面的,文章以刚刚认识的两个人为例!也就是说,他们之前的关系是陌生人,然而在现实当中两人合作也可以有其它的关系,比如说合 ...
- Oracle 过程控制语句整理
分支语句/循环语句 v_case ) :; begin then dbms_output.put_line('条件成立'); elsif then then dbms_output.put_line( ...
- QQ2013登录报文简单分析(不可用于非法用途)
[NO.1 2013-05-08 00:31:16 046 SEND 115字节]02 31 03 08 25 27 B5 88 6F 91 D2 03 00 00 00 0101 01 00 00 ...