VMware + Ubuntu 18.04 + CLion调试 Redis5 源码

奋斗的小皇帝 2020/6/28 17:27:43

前言 Redis 是目前最火热的缓存中间件之一,各大公司在面试时,都会把 Redis 作为重点考察的一部分。但是因为 Redis 是使用 C 语言开发的,它不像我们平时使用 Java、C# 等高级语言,在编辑器中就可以直接看到源码进行学习,学习 Redis 只能通过日常使用,或者遇到问题的…

前言

Redis 是目前最火热的缓存中间件之一,各大公司在面试时,都会把 Redis 作为重点考察的一部分。但是因为 Redis 是使用 C 语言开发的,它不像我们平时使用 Java、C# 等高级语言,在编辑器中就可以直接看到源码进行学习,学习 Redis 只能通过日常使用,或者遇到问题的时候去网上 Google 查找,而这种级别所能学到的知识是不够,要较好的掌握 Redis 的原理,通过源码学习是较好的一条路径,而且 Redis 的源码并不困难,是作为进阶学习 C 语言的优秀教材。

如果你没有 C 语言基础,那么还是推荐你去看看 《C Primer Plus》,如果你有一门高级语言的基础,你会发生 C 比这些高级语言都要简单,唯一需要注意的就是我们常说的指针。作为一个程序员,掌握 C 语言也会使你学习计算机组成原理、计算机网络、操作系统更加轻松。

曾经听过一个行业中的大佬说过:

不会 C 语言的程序员不是一个合格的程序员。

工具介绍

工欲善其事,必先利其器

我们首先要有一些趁手的工具来帮助我们阅读、调试源码,就像开发 Java 应用使用 IDEA 一样,一个趁手的工具可以达到事倍功半的效果。

因为官方提供的 Redis 只支持 Linux 系统,所以我们需要一个 Linux 环境。我们这里使用 VMware 开启一个虚拟机、Ubuntu 18.04 作为操作系统、CLion 作为阅读、调试工具(使用过 IDEA 的同学,肯定可以很快掌握 CLion 的使用,基本没有区别)。

关于 VMware、Ubuntu 18.04、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 文件。

image-20200627221404699

创建完文件之后会出现下图所示的提示,然后我们要点击箭头指向的文字(此时它会提示构建失败,但是不要紧,我们可以不用管)这样它就会将该项目看作是一个 CMake 项目,并且最下方也会出现一个快捷的构建窗口,方便我们后面进行构建项目。

image-20200627222308664

然后将如下内容复制进该文件:

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 文件

image-20200627221515958

然后将如下内容复制进该文件:

add_subdirectory(hiredis)
add_subdirectory(linenoise)
add_subdirectory(lua)
复制代码

第三步

在 dept/lineboise/ 目录下创建一个 CmakeLists.txt 文件

image-20200627221725484

然后将如下内容复制进该文件:

add_library(linenoise linenoise.c)
复制代码

第四步

在 dept/lua/ 目录下创建一个 CmakeLists.txt 文件

image-20200627221853985

然后将如下内容复制进该文件:

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 文件

image-20200627222644164

然后将如下内容复制进该文件:

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"
复制代码

最终如图所示:

image-20200627222840862

开始调试

此时,我们就完成了所有步骤,可以开始调试了。

image-20200627223036394

安装图中数字所示步骤点击,看到图中框中显示的信息则表示编译成功。此时编译器的右上角会出现下图所示的列表

image-20200627223207484

然后,我们选择 redis-server,点击绿色小箭头即可开启 Redis 服务,然后我们就可以在源码中打断点进行调试了。

总结

Redis 的源码中包含了大量的数据结构,我们可以在里面学到 SDS、跳跃表、字典、哈希表、布隆过滤器等等数据结构的实现,并且这些数据结构并不会比我们平时接触到的知识复杂,还想深入一点还可以看看 Redis 是如何使用 epoll 实现多路复用的。

学习 Redis 源码配套此教程效果更佳。

总之,源码是学习一个工具第二好的方式,第一好当然文档啦!

随时随地学软件编程-关注百度小程序和微信小程序
关于找一找教程网

本站文章仅代表作者观点,不代表本站立场,所有文章非营利性免费分享。
本站提供了软件编程、网站开发技术、服务器运维、人工智能等等IT技术文章,希望广大程序员努力学习,让我们用科技改变世界。
[VMware + Ubuntu 18.04 + CLion调试 Redis5 源码]http://www.zyiz.net/tech/detail-141342.html

上一篇:认识Redis高性能背后的数据结构(一)

下一篇:RedLock究竟是不是Redis分布式锁分布式环境下的银弹?

赞(0)

共有 条评论 网友评论

验证码: 看不清楚?
    关注微信小程序
    程序员编程王-随时随地学编程

    扫描二维码或查找【程序员编程王】

    可以随时随地学编程啦!

    技术文章导航 更多>
    扫一扫关注最新编程教程