【注】 本文的源代码分析是基于redis-2.4.3版本的。redis
redisServer主要记录了server的全局信息,如数据库,连入的client,支持的全部操做,从配置文件中读取的配置信息等。数据库
1数据结构 2架构 3并发 4app 5异步 6socket 7函数 8spa 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
|
redisClient主要记录了某个接入客户端的状态信息,如客户端链接句柄,操做的数据库,发送的命令,返回的结果列表等。为每一个client创建一个这种数据结构,能够很方便的支持多用户并发访问。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
|
下图描述了client与redis server的整个交互过程,图中只描述了代码关键路径。
(1)首先,从redis.c文件中的main函数开始:
Main函数首先调用:
1 |
|
该函数主要完成如下功能:设定默认的参数值,并读取配置文件redis.conf,若用户配置了某个参数,则用该参数值替换默认值。
接下来,调用:
1 |
|
该函数主要对server进行初始化,初始化内容包括:
调用anetTcpServer函数建立socket server做为redis server,并将该server的句柄加到epoll/kqueue的监听队列中。一旦有client接入,便会对该client触发操做acceptTcpHandler,该操做是调用aeCreateFileEvent注册的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
|
【注】aeCreateFileEvent函数用于注册监听链接事件,即某个client向server发起链接或者发出一个命令后,会触发这个事件;而aeCreateTimeEvent函数用于注册定时任务serverCron,该函数每隔100 毫秒执行一次,主要进行一些后台处理,如:记日志,清除无效key,清除无效连接。
acceptTcpHandler函数会调用acceptCommonHander,而acceptCommonHander又会调用createClient来为该client建立一个redisClient对象….,最终,redis会根据用户输入的命令调用已经写好的命令执行函数,这些函数已经被写死,保存到一个全局只读表中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
用户输入get命令,redis最终会调用getCommand函数,用户输入set命令,redis最终会调用setCommand函数…..。该表是在initServerConfig()函数中,被加载到一个hash table中的,以便于后面的查找:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
|
(2)redis执行完用户的一个命令后,会将结果写入到redisClient对象中的reply list中,而sendReplyToClient函数会不断的从该list中数据,异步地发送给client。须要注意的是,sendReplyToClient函数也是经过aeCreateFileEvent注册的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
上面只是粗略讲了一下代码架构,只算是抛砖引玉了,若是读者想更进一步了解redis代码架构,最好亲自读一下代码。整体而言,redis代码结构很清晰,架构也是比较简单。