Redis源码解析(1)——源码目录介绍
概念
redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)和zset(有序集合)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
开始
这里我使用的是redis-2.2.2.tar.gz版本的redis(下载地址)首先要对它进行安装,这里我选择使用cygwin工具进行安装,加入我把该压缩包放在F盘下,使用cygwin工具进行shell命令:
1
2
3
|
$ tar xzf redis-2.2.2. tar .gz $ cd redis-2.2.2 $ make |
这里的make实际上操作的是Makefile文件,Makefile按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个shell脚本一样,其中也可以执行操作系统的命令。
浏览下Redis根目录中的Makefile文件:
通过make命令可以执行“cd src && make all”。而此时的make all实际上已经开始执行src目录中的Makefile文件。这个文件比较复杂,大致就是将一系列的c文件以及h文件链接起来,通过cc/gcc编译器将文件生成目标文件o,接着将相应的o目标文件在通过编译器生成exe文件,当你编译完毕后,在src的目录上将产生5个exe文件:
redis-benchmark.exe:用于做性能测试;
redis-check-aof.exe:更新日志检查;
redis-check-dump.exe:用于本地数据库检查;
redis-cli.exe:客户端程序;
redis-server.exe:服务端程序;
具体用法这里不多说了,可以参考(http://www.cnblogs.com/daizhj/articles/1956681.html)
现在来看下src包含的文件(我按照首字母顺序来讲):
adlist.h/adlist.c:用于对list的定义,它是个双向链表结构,从头文件可以找到:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
// list节点 typedef struct listNode { struct listNode *prev; struct listNode *next; void *value; } listNode; // list迭代器 typedef struct listIter { listNode *next; int direction; } listIter; // list数据结构 typedef struct list { listNode *head; listNode *tail; void *(*dup)( void *ptr); void (* free )( void *ptr); int (*match)( void *ptr, void *key); unsigned int len; } list; |
在ListNode节点下包含prev指针和next指针,说明它通过指针将节点进行双向链接。
并且从adlist.h的头文件可以找到非常丰富的方法声明,包括list创建,list释放,list头部/尾部添加节点等等,具体在后面的系列会做出介绍。
ae.h/ae.c:用于Redis的事件处理,包括句柄事件和超时事件。
在ae.c中的头部可以发现:
1
2
3
4
5
6
7
8
9
|
#ifdef HAVE_EPOLL #include "ae_epoll.c" #else #ifdef HAVE_KQUEUE #include "ae_kqueue.c" #else #include "ae_select.c" #endif #endif |
在网络相关操作中,定义了一组公共操作接口:aeApiCreate,aeApiFree,aeApiAddEvent,aeApiDelEvent,aeApiPoll,aeApiName方法。在ae_epoll.c、ae_kqueue.c和ae_select.c中,分别实现了基于epoll/kqueue和select系统调用的接口。系统调用的选择顺序依次为epoll,kqueue,select。
anet.h/anet.c:这两个文件非常重要,作为Server/Client通信的基础封装,包括anetTcpServer,anetTcpConnect,anetTcpAccept,anetRead,anetWrite等等方法。
aof.c:aof,全称为append only file,作用就是记录每次的写操作,在遇到断电等问题时可以用它来恢复数据库状态。但是他不是bin的,而是text的。一行一行,写得很规范.如果你是一台redis,那你也能人肉通过它恢复数据。
config.h/config.c:用于将配置文件redis.conf文件中的配置读取出来的属性通过程序放到server对象中。在main函数(server服务主入口点处)可以发现里面调用loadServerConfig(char *filename)方法,这个方法就是使用config.c里面的方法实现。具体会在后面的系列中详细介绍。
db.c:对于Redis内存数据库的相关操作。
debug.c:用于调试使用。
dict.h/dict.c:也是很重要的两个文件,主要对于内存中的hash进行管理:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
typedef struct dictEntry { void *key; void *val; struct dictEntry *next; } dictEntry; typedef struct dictType { unsigned int (*hashFunction)( const void *key); void *(*keyDup)( void *privdata, const void *key); void *(*valDup)( void *privdata, const void *obj); int (*keyCompare)( void *privdata, const void *key1, const void *key2); void (*keyDestructor)( void *privdata, void *key); void (*valDestructor)( void *privdata, void *obj); } dictType; typedef struct dict { dictType *type; void *privdata; dictht ht[2]; int rehashidx; /* rehashing not in progress if rehashidx == -1 */ int iterators; /* number of iterators currently running */ } dict; |
这里dictEntry作为一个dict字段结构,里面包括key以及value,已经指向下一个dictEntry的指针。dictType作为一些dict的操作结构。dict作为一个hash结构。后面的文章会具体介绍。
fmacros.h:用于Mac下的兼容性处理。
help.h:辅助于命令的提示信息,作用于redis-cli.exe可执行文件中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
struct commandHelp { char *name; char *params; char *summary; int group; char *since; } commandHelp[] = { { "APPEND" , "key value" , "Append a value to a key" , 1, "1.3.3" }, { "AUTH" , "password" , "Authenticate to the server" , 8, "0.08" }, { "BGREWRITEAOF" , "-" , "Asynchronously rewrite the append-only file" , 9, .... }; |
intset.h/intset.c:整数范围内的使用set,并包含相关set操作。
lzf.h/lzf_c.c/lzf_d.c/lzfP.h:对于本地数据库的保存,使用的是LZF压缩算法,很神奇,算法只有200-300行的代码。
multi.c:用于事务处理操作。请看这样的一个例子:
通过执行exec,可以提交整个事务过程,如果你想撤销整个事务过程,你可以使用discard命令:
可以发现get age已经取不到值了,说明discard命令让事务失效。
networking.c:网络协议传输方法定义相关的都放在这个文件里面了。包括让Client连接上Server,让Slave挂接到Master,已经Server/Client之间的信息交互的实现等等。
object.c:用于创建和释放redisObject对象,redisObject结构为:
1
2
3
4
5
6
7
8
9
10
11
12
|
typedef struct redisObject { unsigned type:4; unsigned storage:2; /* REDIS_VM_MEMORY or REDIS_VM_SWAPPING */ unsigned encoding:4; unsigned lru:22; /* lru time (relative to server.lruclock) */ int refcount; void *ptr; /* VM fields are only allocated if VM is active, otherwise the * object allocation function will just allocate * sizeof(redisObjct) minus sizeof(redisObjectVM), so using * Redis without VM active will not have any overhead. */ } robj; |
pqsort.h/pqsort.c/sort.c:关于排序算法,sort.c具体作为Redis场景下的排序实现。
pubsub.c:用于订阅模式的实现,有点类似于Client广播发送的方式。
rdb.c:对于Redis本地数据库的相关操作,默认文件是dump.rdb(通过配置文件获得),包括的操作包括保存,移除,查询等等。
redis-benchmark.c:用于redis性能测试的实现。请看main方法以下设置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
config.debug = 0; config.numclients = 50; config.requests = 10000; config.liveclients = 0; config.el = aeCreateEventLoop(); aeCreateTimeEvent(config.el,1,showThroughput,NULL,NULL); config.keepalive = 1; config.donerequests = 0; config.datasize = 3; config.randomkeys = 0; config.randomkeys_keyspacelen = 0; config.quiet = 0; config.loop = 0; config.idlemode = 0; config.latency = NULL; config.clients = listCreate(); config.hostip = "127.0.0.1" ; config.hostport = 6379; config.hostsocket = NULL; parseOptions(argc,argv); config.latency = zmalloc( sizeof ( long long )*config.requests); |
默认性能测试中的客户端数量为50个,并行发送的请求有10000条,你也可以通过redis-benchmark命令行参数进行设置。
redis-check-aof.c:用于更新日志检查的实现。
redis-check-dump.c:用于本地数据库检查的实现。
redis-cli.c:客户端程序的实现。具体会在后面的文章详细介绍。
redis.h/redis.c:服务端程序的实现。具体会在后面的文章详细介绍。
release.h/release.c:用于发布使用。
replication.c:用于主从数据库的复制操作的实现。
sds.h/sds.c:用于对字符串的定义,从头文件可以找到:
1
2
3
4
5
6
|
//字符串 struct sdshdr { int len; int free ; char buf[]; }; |
还可以看到对于字符串的相关操作,包括复制,连接,清零等等。
sha1.h/sha1.c:有关于sha算法的实现。
solarisfixes.h:Solaris系统的兼容性实现。
syncio.c:用于同步Socket和文件I/O操作。
t_hash.c/t_list.c/t_set.c/t_string.c/t_zset.c:hash,list,set,string,zset在Server/Client中的应答操作。主要通过redisObject进行类型转换。
testhelp.h:一个C风格的小型测试框架。
util.c:关于通用工具的方法实现。
version.h:Redis版本号定义。
vm.c:关于虚拟内存的管理实现。
zipmap.h/zipmap.c:zipmap是一个类似于hash的存储对象。在新建一个hash对象时开始是用zipmap(又称为small hash)来存储的。这个zipmap其实并不是hash table但是zipmap相比正常的hash实现可以节省不少hash本身需要的一些元数据存储开销,如果field或者value的大小超出一定限制后,redis会在内部自动将zipmap替换成正常的hash实现。
ziplist.h/ziplist.c:ziplist是一个类似于list的存储对象。它的原理类似于zipmap。
zmalloc.h/zmalloc.c:关于Redis的内存分配的封装实现。
Redis源码解析(1)——源码目录介绍的更多相关文章
- 《Flink 源码解析》—— 源码编译运行
更新一篇知识星球里面的源码分析文章,去年写的,周末自己录了个视频,大家看下效果好吗?如果好的话,后面补录发在知识星球里面的其他源码解析文章. 前言 之前自己本地 clone 了 Flink 的源码,编 ...
- AOP源码解析:AspectJAwareAdvisorAutoProxyCreator类的介绍
AspectJAwareAdvisorAutoProxyCreator 的类图 上图中一些 类/接口 的介绍: AspectJAwareAdvisorAutoProxyCreator : 公开了Asp ...
- 微信小程序扫码解析小程序码
通过微信扫小程序码,跳转到应用小程序内, 如何解析小程序码的参数呢? 一般小程序码会跳转到设置的页面,如首页, 可以直接跳转到小程序首页,然后解析小程序携带的参数,再打开某个页面. (小程序码的路径要 ...
- Vue源码解析-调试环境-代码目录和运行构建
目录 前言 1 代码结构 1.1 octotree插件 1.2 vue工程项目目录 1.3 主要代码目录src compiler core platforms server sfc shared 2 ...
- spring源码解析——spring源码导入eclipse
一.前言 众所周知,spring的强大之处.几乎所有的企业级开发中,都使用了spring了.在日常的开发中,我们是否只知道spring的配置,以及简单的使用场景.对其实现的代码没有进行深入的了 ...
- MIT 2012分布式课程基础源码解析一-源码概述
课程主页 课程介绍:本课程会在给出的源码的基础上要求完成8个lab Lab overviewLab 1 - Lock ServerLab 2 - Basic File ServerLab 3 - MK ...
- 『Python』源码解析_源码文件介绍
本篇代码针对2.X版本,与3.X版本细节不尽相同,由于两者架构差别不大加之本人能力有限,所以就使用2.X体验python的底层原理了. 一.主要文件夹内容 Include :该目录下包含了Python ...
- 源码解析-knockout源码准备
准备包括心理和资源两方面. 心理 我看过一句话说,当你用一个框架时,不要忙着看一遍使用教程就开始写项目,先去看看框架原理. 这句话我深以为然.现今前端快速发展,很多前端攻城狮都很茫然:框架更新太快了, ...
- 开源项目源码解析-PhotoView 源码解析
1. 功能介绍 特性(Features): 支持 Pinch 手势自由缩放. 支持双击放大/还原. 支持平滑滚动. 在滑动父控件下能够运行良好.(例如:ViewPager) 支持基于 Matrix 变 ...
- [Bootstrap 源码解析]——bootstrap源码之初始化
bootstrap源码之初始化 我们先来分析normalize.less编译后的源码,我们知道normalize.css是一个专门将不同浏览器的默认css特性设置为统一效果的css库,它和reset. ...
随机推荐
- 印象笔记ipad端快捷键
- 隐马尔可夫模型(hidden Markov model,HMM)
定义: 隐马尔科夫模型是关于时序的概率模型,描述由一个隐藏的马尔可夫链随机生成不可观测的状态随机序列,再由各个状态生成一个观测而产生观测随机序列的过程. 隐马尔科夫模型由初始概率分布.状态转移概率分布 ...
- MySQL数据库(3)_MySQL数据库表记录操作语句
附: MYSQL5.7版本sql_mode=only_full_group_by问题 .查询当前sql_mode: select @@sql_mode .查询出来的值为: set @@sql_mode ...
- 安装mysql到ubuntu
Ubuntu 16.04上安装MySQL步骤: 如果你使用的是Ubuntu 16.04以前的版本,可以看这里:Ubuntu 14.04/15.10升级到Ubuntu 16.04 LTS.一. 安装My ...
- 【leetcode刷题笔记】Word Ladder II
Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from ...
- Linux环境下的图形系统和AMD R600显卡编程(1)——Linux环境下的图形系统简介
转:https://www.cnblogs.com/shoemaker/p/linux_graphics01.html Linux/Unix环境下最早的图形系统是Xorg图形系统,Xorg图形系统通过 ...
- Squid 反向代理配置
Squid 反向代理配置 1.删除主配置文件重写写入配置 rm -f /etc/squid/squid.conf 2.重新写入配置反向代理 vim /etc/squid/squid.conf # 监听 ...
- nodejs异步调用async
犹豫nodejs是异步编程模型,有一些在同步编程中很容易做到的事情,现在却变得很麻烦,async的流程控制就是为了简化这些操作var async = require('async'); 1.serie ...
- php数组函数-array_pop()
array_pop()函数删除数组中的最后一个元素(出栈). array_pop(array) array:必需.规定数组 返回值:返回数组的最后一个值.如果数组是空,或者不是一个数组,将返回NULL ...
- cocos2dx打飞机项目笔记一:项目结构介绍
最近在学习cocos2dx引擎,版本是2.1.3,开发环境是win7 + vs2010,模仿微信打飞机游戏,开发中参考了 csdn 偶尔e网事 的系列文章:http://blog.csdn.net/c ...