Redis 是目前最火热的缓存中间件之一,各大公司在面试时,都会把 Redis 做为重点考察的一部分。可是由于 Redis 是使用 C 语言开发的,它不像咱们平时使用 Java、C# 等高级语言,在编辑器中就能够直接看到源码进行学习,学习 Redis 只能经过平常使用,或者遇到问题的时候去网上 Google 查找,而这种级别所能学到的知识是不够,要较好的掌握 Redis 的原理,经过源码学习是较好的一条路径,并且 Redis 的源码并不困难,是做为进阶学习 C 语言的优秀教材。git
若是你没有 C 语言基础,那么仍是推荐你去看看 《C Primer Plus》,若是你有一门高级语言的基础,你会发生 C 比这些高级语言都要简单,惟一须要注意的就是咱们常说的指针。做为一个程序员,掌握 C 语言也会使你学习计算机组成原理、计算机网络、操做系统更加轻松。程序员
曾经听过一个行业中的大佬说过:面试
不会 C 语言的程序员不是一个合格的程序员。redis
工欲善其事,必先利其器json
咱们首先要有一些趁手的工具来帮助咱们阅读、调试源码,就像开发 Java 应用使用 IDEA 同样,一个趁手的工具能够达到事倍功半的效果。api
由于官方提供的 Redis 只支持 Linux 系统,因此咱们须要一个 Linux 环境。咱们这里使用 VMware 开启一个虚拟机、Ubuntu 18.04 做为操做系统、CLion 做为阅读、调试工具(使用过 IDEA 的同窗,确定能够很快掌握 CLion 的使用,基本没有区别)。缓存
关于 VMware、Ubuntu 18.0四、CLion 的安装这里就再也不赘述了,由于都是很简单的步骤,若是连这一步都能拦住你,那么能够 Google 一下,有不少教程能够帮你跨过这个小坎。网络
源码能够直接从 Github 上克隆下来,若是从 Github 上克隆的速度较慢,能够从这个连接克隆:gitee.com/lhd951220/r…数据结构
总所周知,直接从 Github 上克隆项目会比较慢,这里建议你们能够开通一个 Gitee 帐户,而后把须要从 Github 上的克隆的源码导入到 Gitee 中,而后使用 Gitee 上的连接进行下载,你会体验到什么叫飞通常的速度。关于这里的教程也很简单,网上也有不少资源,能够自行搜索。编辑器
首先,须要介绍一下,CLion 是使用 CMake 做为项目构建工具的,这里不须要知道 CMake 是什么(我也不是很懂),大概理解为 Maven 就能够了。
CMake 是经过一种 CMakeLists.txt
文件来构建项目的,因此咱们首先须要建立一个该文件。
注意:咱们在克隆完项目的时候,最后将分支切换到 commitId 为 767977c 的分支,由于我发现一些分支缺乏部分文件,没法构建。切换的方法很简单,直接在命令行执行 git checkout 767977c
在项目的主目录下建立一个CMakeLists.txt
文件。
建立完文件以后会出现下图所示的提示,而后咱们要点击箭头指向的文字(此时它会提示构建失败,可是没关系,咱们能够不用管)这样它就会将该项目看做是一个 CMake 项目,而且最下方也会出现一个快捷的构建窗口,方便咱们后面进行构建项目。
而后将以下内容复制进该文件:
cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
project(redis VERSION 5.0)
set(CMAKE_BUILD_TYPE "Debug")
get_filename_component(REDIS_ROOT "${CMAKE_CURRENT_SOURCE_DIR}" ABSOLUTE)
execute_process(
COMMAND sh -c ./mkreleasehdr.sh
WORKING_DIRECTORY ${REDIS_ROOT}/src/
)
add_subdirectory(deps)
add_subdirectory(src/modules)
set(SRC_SERVER_TMP
src/adlist.c
src/acl.c
src/ae.c
src/anet.c
src/ae_epoll.c
src/dict.c
src/sds.c
src/zmalloc.c
src/lzf_c.c
src/lzf_d.c
src/pqsort.c
src/zipmap.c
src/sha1.c
src/sha256.c
src/ziplist.c
src/release.c
src/networking.c
src/util.c
src/object.c
src/db.c
src/replication.c
src/rdb.c
src/t_string.c
src/t_stream.c
src/t_list.c
src/t_set.c
src/t_zset.c
src/timeout.c
src/tls.c
src/evict.c
src/defrag.c
src/module.c
src/quicklist.c
src/expire.c
src/childinfo.c
src/redis-check-aof.c
src/redis-check-rdb.c
src/lazyfree.c
src/geohash.c
src/gopher.c
src/rax.c
src/geohash_helper.c
src/siphash.c
src/geo.c
src/t_hash.c
src/config.c
src/connection.c
src/aof.c
src/pubsub.c
src/multi.c
src/debug.c
src/sort.c
src/intset.c
src/syncio.c
src/cluster.c
src/crc16.c
src/endianconv.c
src/slowlog.c
src/scripting.c
src/bio.c
src/rio.c
src/rand.c
src/memtest.c
src/crc64.c
src/bitops.c
src/sentinel.c
src/notify.c
src/setproctitle.c
src/blocked.c
src/hyperloglog.c
src/latency.c
src/sparkline.c
src/t_stream.c
src/lolwut.c
src/tracking.c
src/lolwut5.c
src/lolwut6.c
src/listpack.c
src/localtime.c
)
set(SRC_SERVER src/server.c ${SRC_SERVER_TMP})
set(SRC_CLI
src/anet.c
src/sds.c
src/adlist.c
src/redis-cli.c
src/zmalloc.c
src/release.c
src/anet.c
src/ae.c
src/crc64.c
src/crc16.c
src/dict.c
src/siphash.c
)
set(EXECUTABLE_OUTPUT_PATH src)
link_directories(deps/linenoise/ deps/lua/src deps/hiredis)
add_executable(redis-server ${SRC_SERVER})
target_include_directories(redis-server
PRIVATE ${REDIS_ROOT}/deps/linenoise
PRIVATE ${REDIS_ROOT}/deps/hiredis
PRIVATE ${REDIS_ROOT}/deps/lua/src)
target_link_libraries(redis-server
PRIVATE dl
PRIVATE pthread
PRIVATE m
PRIVATE lua
PRIVATE linenoise
PRIVATE hiredis)
add_executable(redis-cli ${SRC_CLI})
target_include_directories(redis-cli
PRIVATE ${REDIS_ROOT}/deps/linenoise
PRIVATE ${REDIS_ROOT}/deps/hiredis
PRIVATE ${REDIS_ROOT}/deps/lua/src)
target_link_libraries(redis-cli
PRIVATE pthread
PRIVATE m
PRIVATE linenoise
PRIVATE hiredis
)
复制代码
在 dept/ 目录下也建立一个 CMakeLists.txt
文件
而后将以下内容复制进该文件:
add_subdirectory(hiredis)
add_subdirectory(linenoise)
add_subdirectory(lua)
复制代码
在 dept/lineboise/ 目录下建立一个 CmakeLists.txt
文件
而后将以下内容复制进该文件:
add_library(linenoise linenoise.c)
复制代码
在 dept/lua/ 目录下建立一个 CmakeLists.txt
文件
而后将以下内容复制进该文件:
set(LUA_SRC
src/lapi.c src/lcode.c src/ldebug.c src/ldo.c src/ldump.c src/lfunc.c
src/lgc.c src/llex.c src/lmem.c
src/lobject.c src/lopcodes.c src/lparser.c src/lstate.c src/lstring.c
src/ltable.c src/ltm.c
src/lundump.c src/lvm.c src/lzio.c src/strbuf.c src/fpconv.c
src/lauxlib.c src/lbaselib.c src/ldblib.c src/liolib.c src/lmathlib.c
src/loslib.c src/ltablib.c
src/lstrlib.c src/loadlib.c src/linit.c src/lua_cjson.c
src/lua_struct.c
src/lua_cmsgpack.c
src/lua_bit.c
)
add_library(lua STATIC ${LUA_SRC})
复制代码
到了这一步,咱们已经完成一大半了。
在 src/modules/ 目录下建立一个 CmakeLists.txt
文件
而后将以下内容复制进该文件:
cmake_minimum_required(VERSION 3.9)
set(CMAKE_BUILD_TYPE "Debug")
add_library(helloworld SHARED helloworld.c)
set_target_properties(helloworld PROPERTIES PREFIX "" SUFFIX ".so")
add_library(hellotype SHARED hellotype.c)
set_target_properties(hellotype PROPERTIES PREFIX "" SUFFIX ".so")
add_library(helloblock SHARED helloblock.c)
set_target_properties(helloblock PROPERTIES PREFIX "" SUFFIX ".so")
add_library(testmodule SHARED testmodule.c)
set_target_properties(testmodule PROPERTIES PREFIX "" SUFFIX ".so")
复制代码
在 src/ae_epoll.c 文件下添加下面代码
#include "ae.h"
#include <zconf.h>
#include "zmalloc.h"
复制代码
最终如图所示:
此时,咱们就完成了全部步骤,能够开始调试了。
安装图中数字所示步骤点击,看到图中框中显示的信息则表示编译成功。此时编译器的右上角会出现下图所示的列表
而后,咱们选择 redis-server,点击绿色小箭头便可开启 Redis 服务,而后咱们就能够在源码中打断点进行调试了。
Redis 的源码中包含了大量的数据结构,咱们能够在里面学到 SDS、跳跃表、字典、哈希表、布隆过滤器等等数据结构的实现,而且这些数据结构并不会比咱们平时接触到的知识复杂,还想深刻一点还能够看看 Redis 是如何使用 epoll 实现多路复用的。
学习 Redis 源码配套此教程效果更佳。
总之,源码是学习一个工具第二好的方式,第一好固然文档啦!