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万 内存读取数据,断电的时候数 ...
随机推荐
- php -l 检查文件是否语法错误
有时候在进行网页开发的时候,后台文件的语法错误比较难检查出来,这时候使用php -l filename可对文件的语法进行检查.
- 位运算取第一个非0的位 r & (~(r-1))
Single Number III Given an array of numbers nums, in which exactly two elements appear only once and ...
- ThinkPHP中数据库操作返回值总结
转自:http://www.baiwar.com/post/thinkphp-database-operations-in-the-return-value.html Thinkphp中的Think\ ...
- JDE报表开发笔记(R5537011 收货校验统计表)
业务场景:根据批次收货,收货后对该批次产品进行检验,记录检验结果生成统计表. 涉及表:主表F37011,业务从表F43121/F4101/F4108 ------------------------- ...
- 关于linux的磁盘管理
普通的做法就是检索文件的时间,并使用rm进行删除. 另外有一种做法,可以通过检索inode,进一步进行文件的删除. 下面的文章为摘录,帮助了解inode: 文件名 -> inode -> ...
- MySQL主从数据库同步
更新中,还未测试.......
- Windows系统安装时间
http://www.45it.com/windowszh/201206/30693.htm 修改系统安装时间 开始" - "运行" - 输入"regedit& ...
- 看项目得到info_freeCsdn-01闪屏页面
/** * 渐变展示启动屏 */ private void startAnimation() { Animation aa = new Animation() { }; aa.setDuration( ...
- Keil 4.0 生成bin文件
在菜单:Flash /configuare falsh tools ... option for Tatget '项目' /User中:在Run User Programs After Build/R ...
- App Store--心酸的上线路,说说那些不可思议的被拒理由
yoyeayoyea 您的应用包括色情内容(色情交易,色情展示). 原因是我们的销售人员,把几张艺术照放在个人相册里(头像),换成卡通头像,通过. 颜小风 被拒很正常 一次通过不正常. 之前上线 ...