最近突然一时兴起,开始看redis的源代码实现。《redis源码阅读笔记》系列将记录下我阅读redis源码的一些笔记和心得。
第一篇我们从最简单的sds(Simple Dynamic String,简单动态字符串)开始啦。
网上已经有一些很好的代码解析的文章了,所以我们可以参考一下
1.高层视角解读
SDS 的定义
SDS 与 C 字符串的区别
比起C字符串,SDS具有以下优点:
- 常数复杂度获取字符串长度。
- 杜绝缓冲区溢出。
- 减少修改字符串长度时所需的内存重分配次数。
- 二进制安全。
- 兼容部分C字符串函数。
2.底层视角解读
接下来就可以阅读源码了(sds.h,sds.c两个文件)。
然后结合这篇文章看,
Redis String类型实现原理
3.疑难点解惑
Q:为何代码中是int,解释中说long型。原文:“巧合的是两个long型的长度加起来正好是struct sdshdr的长度。”
A:好吧,其实C语言里,32位系统上,int和long是一样的,这两个都是32位,而long long型才是64位的。
sizeoftest.c运行结果
sizeof(int) = 4
sizeof(long) = 4
sizeof(long long) = 8
sizeof(size_t) = 4
sizeof(char *) = 4
Q:size_t什么意思
A:size_t 类型定义在cstddef头文件中,它是一个与机器相关的unsigned类型,其大小足以保证存储内存中对象的大小。
看一下在stddef.h中的定义
#define __SIZE_TYPE__ long unsigned int
在32位系统中size_t是4字节的,而在64位系统中,size_t是8字节的,这样利用该类型可以增强程序的可移植性。换句话说,一个指针可以被安全地放进为size_t类型。
C函数库中strlen的定义
size_t strlen (const char *s)
这样定义意思是返回的数肯定是大于等于0的,所以一般都用size_t这个类型。所以还是习惯,大师都这么用,所以就这么写。
Q:sdslen函数的定义里inline什么意思
A:内联函数用来建议编译器将指定的函数代码插入并取代每一处调用该函数的地方,从而节省了调用函数带来的额外开销。类似于写程序时将同样的代码复制粘贴到多处。好处是减少执行时间,坏处就是增加了重复代码占用的空间。
Q:static什么意思
A:static意味着该函数只在这个文件中可见,还意味着可以在其他文件中定义同名函数。
Q:为什么static inline一起用
A:这个我查了几篇文章,解释的比较复杂,看不大懂。简单的说,这个成了C99里的一个习惯了吧,大家都这么写,你就这么写吧,而且static inline函数一般都是定义在头文件(h)中。这样包含这个h文件的c文件都将拥有这个函数定义。
Q:数据空间的char buf[]什么意思,能改成char* buf吗?
A:有区别。这个比较复杂了,char buf[]是flexible array member,是一个编程技巧,
http://c-faq.com/struct/structhack.html
不是一句话能讲明白的。请耐心看完下面的解释。
c99之 柔性数组成员 flexible array member
请参考这篇文章,我不重复复制了。
c99之 柔性数组成员
我做了一个试验,将原来的代码片段改用char* buf的形式重写了。
比较一下和原来的不同
sds1test.c
memcpy(sh->buf, str1, strlen(str1));
sh->buf[initlen] = '\0';
sds2test.c
strcpy(sh + 1, str1);
sh->buf = sh + 1;
sds1test.c运行结果
sizeof(struct sdshdr) = 8
strlen(str2) = 5
address of sh = 537335688
address of str2 = 537335696
str2 - sh = 8
sdslen = 5
sds2test.c运行结果
sizeof(struct sdshdr) = 12
strlen(str2) = 5
address of sh = 537335688
address of str2 = 537335700
str2 - sh = 12
sdslen = 5
可以看到改成char* buf的形式后,struct体占用空间多了4个字节,而且给buf的赋值要用sh->buf = sh + 1这种古怪的形式,不方便。
这个技巧用的真是令人拍案叫绝哪!
上图左边是原来redis的实现,struct体只占用8个字节,右边是改成char* buf的形式后,struct体占用12个字节。
到此,相信读者对“巧合的是两个long型的长度加起来正好是struct sdshdr的长度。” 这句话就可以理解了。
最后看一下这个网页的解释,可以看到这是一个经常用到的技巧。
comp.lang.c FAQ list · Question 2.6
附件是我的测试代码,可以下载下来运行,细细体会flexible array member的精妙。
- 大小: 31 KB
分享到:
相关推荐
Redis是一款高性能的键值对数据库,其内部使用了许多优化的数据结构来存储数据,其中ziplist是Redis为了节省内存而设计...在阅读Redis源码时,深入分析ziplist的实现细节将有助于我们更好地理解和调试Redis的内存管理。
在Redis源码阅读笔记(10)——事件中,我们将探讨Redis如何利用事件模型来实现非阻塞I/O,以及相关的编程模型如Reactor模式和NIO。 Redis使用了一个基于epoll的事件处理器,epoll是Linux系统提供的一种高效I/O多路...
这篇源码阅读笔记主要关注Redis中的对象系统,它是Redis实现高效数据操作的关键。 在Redis中,每个数据都有一个特定的对象类型,比如`OBJ_STRING`、`OBJ_HASH`等,这些类型定义了数据的存储方式和操作行为。对象...
redis源码阅读中文分析注释
Redis 安装遇到的问题——Linux Centos7.5 Redis 是一个开源的、基于内存的数据结构存储系统,常用于数据库、缓存、消息队列等场景。但是,在 Linux Centos7.5 环境中安装 Redis 时可能会遇到一些问题,这篇文章将...
Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。 附件里面包括redis源码,phpredis源码,redis指令及文档
Redis,即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。...本文适合Redis初学者和进阶者阅读,是一份全面而实用的学习笔记。
通过阅读“狂神redis源码笔记”和解压的“redis-study”文件,你将能够深入理解Redis的内部运作,掌握Java客户端的使用技巧,提升在实际项目中运用Redis的能力。这包括但不限于了解Redis的设计模式、源码实现细节、...
1. Scala代码示例:文件中给出了一段Scala代码示例,该示例展示了如何使用Scala连接到配置了哨兵模式的Redis服务器。 2. 使用的库和依赖:该代码示例使用了rediscala库来实现Scala与Redis之间的交互。具体版本为...
1. **多平台支持**:Redis Desktop Manager可在Windows、Mac OS X和Linux等操作系统上运行,适应不同开发环境的需求。 2. **连接管理**:你可以保存多个Redis服务器的连接配置,包括主机名、端口、密码和认证方式,...
Redis全套学习笔记 完整版pdf.rar set:添加键值对 get:获取值 apend:追价值 strlen:获取值的长度 setnx:key不存在时,设置key的值 incr:原子递增1 decr:原子递减1 incrby/decrby:递增或者递减指定的数字 ...
Redis全套学习笔记 Redis是一种基于内存的NoSQL数据库,具有高性能、可扩展性和灵活性等特点。以下是Redis的详细知识点: 安装和启动 * 安装Redis可以通过下载软件包或使用yum、apt-get等安装工具进行安装。 * ...
1. Redis核心架构: Redis基于单线程模型,通过事件驱动机制处理客户端请求。它使用I/O多路复用(例如epoll或kqueue)来高效地处理大量并发连接,确保系统性能不受连接数增加的影响。在Windows环境下,Redis使用...
Redis源码阅读参考资料 Redis是缓存数据库管理系统的核心组件之一,作为一个开源的in-memory数据存储系统,Redis提供了高性能的数据存储和检索功能。为了更好地理解Redis的工作原理和实现机制,本文将从Redis的源码...
**一、Redis源码安装** 1. **下载源码** 首先,我们需要从Redis官方网站或者GitHub仓库下载源码。在这个例子中,我们使用的是`redis-2.8.9.tar.gz`。你可以通过命令行工具如`wget`或`curl`来下载,或者直接在网页...
1. Redis 概述与安装: Redis 安装简单,可以通过源码编译或使用包管理器安装。启动Redis有前台和后台两种方式,后台启动更常见。Redis 可通过`redis-cli`命令行工具进行交互,提供一系列命令用于操作数据库。 2. ...
【Redis完整版笔记】深入解析Redis作为NoSQL数据库的关键特性 Redis是一款高性能的Key-Value内存数据库,广泛应用于缓存、消息队列、计数器等多个场景。在NoSQL数据库的大潮中,Redis以其出色的速度和灵活性...