• 作者:老汪软件技巧
  • 发表时间:2024-11-28 15:07
  • 浏览量:

1 Redis 的简介

Redis 实际上是简称,全称为 Remote Dictionary Server (远程字典服务器),由 Salvatore Sanfilippo 写的高性能 key-value 存储系统,其完全开源免费,遵守 BSD 协议。Redis 与其他 key-value 缓存产品(如 memcache)有以下几个特点。

Redis 也是一种 分布式缓存 [[1. 从缓存到分布式缓存]],其代码是 c 语言写的,那我们该如何阅读呢?

2 环境搭建

环境依赖,先看看 gcc 、cc、g++ 有没有安装

whereis gcc
whereis cc
whereis g++

安装gcc

xcode-select --install  
brew install gcc  
brew install pkg-config

查看 gcc 的版本:

$ gcc --version
Apple clang version 14.0.0 (clang-1400.0.29.202)
Target: x86_64-apple-darwin22.1.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

我使用 CLion 2022.3.1 ,这个版本可以支持 Makefile 的项目,我们可以检查一下环境是不是有问题, 如果有问题,这里会有错误信息,我的之前报错是因为 Clion 的版本版本太低了,升级之后就好了。

下载Redis源码:

git clone https://github.com/redis/redis.git

切换到指定的版本

git checkout 7.0

File => New CMake Project from Sources, 打开源码项目, 会自动生成根目录下的 CMakeList.txt 文件:Clion 导入项目的时候选择已有的 MakeFile 文件,如果有是否 clean 项目,选择 clean 即可,之后可以点开 MakeFile 文件:

如果需要禁止编译器优化,可以使用下面命令:

make CFLAGS="-g -O0" MALLOC=jemalloc

运行完之后, Src 文件下就会出现可运行文件:

然后可以看到这些可运行的选项,继而配置Edit configuration 运行配置:

选择 debug 进行启动,启动成功,然后可以进行调试了:

可以使用 Redis Desktop Manager 来进行连接:

或者命令行连接(没有密码就可以不需要 -a 12345):

redis-cli -h 127.0.0.1 -p 6379 -a 12345

如果头文件引入报红色下划线,那就试试重新加载一下

3 Redis源码阅读技巧3.1 Redis 的目录结构

Redis 的目录:

src:源代码test:测试代码utils:工具类Makefile:编译文件redis.conf : redis 启动的配置文件sentinel.conf:哨兵配置3.2 Redis 源码阅读顺序

网上的源码阅读顺序(引自网上):

从大方向来说,学习 Redis 会有两种路径:

先从启动 Redis 开始,跟着启动顺序读源码,跟着具体的操作读源码

个人建议是先学习如何启动 Redis,抓大放小(大致知道哪个类启动,读那些配置文件,大概是做什么用的),学习 Redis 到底能干什么,大致知道 Redis 的一些用法之后,再去了解 Redis 的常用的数据结构,到底怎么实现的,这个时候对 Redis 的一些数据结构大致有印象,之后可以跟着 Redis 启动,执行命令去看具体功能执行的路径。在 Debug 的过程中,可以加深影响,更加了解数据结构的设计,代码的调用关系。

4 C语言的知识4.1 #define的基本用法

在C语言中,常量是使用频率很高的一个量。常量是指在程序运行过程中,其值不能被改变的量。常量常使用 #define来定义。使用#define定义的常量也称为符号常量,可以提高程序的运行效率,Redis 的源代码中有比较多的地方都使用该方式。

一般有以下两种用法:

_源码阅读技巧_源码阅读软件

#define 宏名 宏值
#define 宏名(参数列表) 表达式

第一种就是定义常量,比如:

#define N 100

此后直到 #undef N之前, N的值都是100。当遇到#undef N,其后如果再出现 N,则 N 需要重新定义之后才可以使用。

第二种语法常用来定义符号函数。例如:

#define AREA(x,y) (x)*(y)

表示用来求长和宽分别是x和y的矩形的面积。需要注意的是,在表达式(x) * (y)中,x和y都要使用“()”括起来,这是因为符号函数在编译时时进行符号形式替换。如果不加()则可能会发生意想不到的错误,例如:

#define AREA(x,y)  x*y
...
A = AREA( 2+3, 1+2 );

此处预期的结果是15,但是实际的结果却是7,这是因为该段代码在编译进行了简单的符号替换而得到的实际表达式是:A = 2+3 * 1+2;

根据运算符的优先级,先进行乘法运算,然后才是加法,这就导致了错误。而如果使用

#define AREA(x,y)  (x)*(y)
...
A = AREA( 2+3, 1+2 );

则在编译时替换的结果是:

A = (2+3) * (1+2);

#include"stdio.h"  
#define AREA(x,y)  (x)*(y)  
int main()  
{  
    int a = AREA(2+3, 1+2);  
   printf( " %d\n", a);  
   return 0;  
}

4.2 头文件

Redis 是使用 c 语言写的,里面有很多头文件:

#include "server.h"  
#include "monotonic.h"  
#include "cluster.h"  
#include "slowlog.h"  
#include "bio.h"  
#include "latency.h"  
#include "atomicvar.h"  
#include "mt19937-64.h"  
#include "functions.h"  
#include "syscheck.h"  
  
#include 

以 实践 --> 抓大放小 --> 带疑问看源码 --> 重构知识图谱 --> 关联知识 --> 跳出细节俯瞰全局,最终完成 Redis 相关的知识学习,并形成一套自己的方法论。