文章来源:http://blog.96work.cn/index.php/archives/125/

本文涉及到的内容,是在CentOS7.8上安装Redis5.0.8出现的问题。


一、第一次执行make

make[3]: gcc:命令未找到
make[3]: *** [net.o] 错误 127
make[3]: 离开目录“/usr/local/src/redis-5.0.8/deps/hiredis”
make[2]: *** [hiredis] 错误 2
make[2]: 离开目录“/usr/local/src/redis-5.0.8/deps”
make[1]: [persist-settings] 错误 2 (忽略)
    CC adlist.o
/bin/sh: cc: 未找到命令
make[1]: *** [adlist.o] 错误 127
make[1]: 离开目录“/usr/local/src/redis-5.0.8/src”
make: *** [all] 错误 2

解决办法:

[root@slave1 redis-5.0.8]# yum -y install gcc gcc-c++
[root@slave1 redis-5.0.8]# make clean

二、第二次执行make

zmalloc.h:50:31: 致命错误:jemalloc/jemalloc.h:没有那个文件或目录
 #include <jemalloc/jemalloc.h>
                               ^
编译中断。

解决办法:

[root@slave1 redis-5.0.8]# yum -y install jemalloc jemalloc-devel
[root@slave1 redis-5.0.8]# make clean

三、第三次执行make

cc: 错误:../deps/hiredis/libhiredis.a:没有那个文件或目录
cc: 错误:../deps/lua/src/liblua.a:没有那个文件或目录
cc: 错误:../deps/jemalloc/lib/libjemalloc.a:没有那个文件或目录
make[1]: *** [redis-server] 错误 1
make[1]: 离开目录“/usr/local/src/redis-5.0.8/src”
make: *** [all] 错误 2

四、分析

阅读了一下Redis5.0.8源码包里的README.md文件,文件中提到:

Redis has some dependencies which are included into the `deps` directory.
`make` does not automatically rebuild dependencies even if something in
the source code of dependencies changes.

意思就是说:Redis有一些依赖被包含在“deps”目录。即使一些依赖的源码发生改变,make也不会自动重构依赖。所以需要执行“make distclean”来完全清理。

对比一下“make clean”和“make distclean”,发现“make distclean”除了清理./src目录下的内容,还对./deps目录下的内容做了清理,各自的输出如下。

“make clean”

[root@slave1 redis-5.0.8]# make clean
cd src && make clean
make[1]: 进入目录“/usr/local/src/redis-5.0.8/src”
rm -rf redis-server redis-sentinel redis-cli redis-benchmark redis-check-rdb redis-check-aof *.o *.gcda *.gcno *.gcov redis.info lcov-html Makefile.dep dict-benchmark
make[1]: 离开目录“/usr/local/src/redis-5.0.8/src”

“make distclean”

[root@slave1 redis-5.0.8]# make distclean
cd src && make distclean
make[1]: 进入目录“/usr/local/src/redis-5.0.8/src”
rm -rf redis-server redis-sentinel redis-cli redis-benchmark redis-check-rdb redis-check-aof *.o *.gcda *.gcno *.gcov redis.info lcov-html Makefile.dep dict-benchmark
(cd ../deps && make distclean)
make[2]: 进入目录“/usr/local/src/redis-5.0.8/deps”
(cd hiredis && make clean) > /dev/null || true
(cd linenoise && make clean) > /dev/null || true
(cd lua && make clean) > /dev/null || true
(cd jemalloc && [ -f Makefile ] && make distclean) > /dev/null || true
(rm -f .make-*)
make[2]: 离开目录“/usr/local/src/redis-5.0.8/deps”
(rm -f .make-*)
make[1]: 离开目录“/usr/local/src/redis-5.0.8/src”

经过以上的步骤,问题已经很明显了。第一次执行make时由于缺少gcc导致出错,在安装完gcc之后执行了“make clean”,并没有清理./deps目录下第一次make时生成的内容,导致了之后的问题。


五、网上关于“致命错误:jemalloc/jemalloc.h”的文章

在出现问题时,也在网上搜索一些个人博客的文章来尝试解决问题,这些文章的解决办法很一致,就是在make时强制使用libc malloc。执行命令如下:

make MALLOC=libc

在Redis的README.md文件中也提到了相关的内容:

Selecting a non-default memory allocator when building Redis is done by setting
the `MALLOC` environment variable. Redis is compiled and linked against libc
malloc by default, with the exception of jemalloc being the default on Linux
systems. This default was picked because jemalloc has proven to have fewer
fragmentation problems than libc malloc.

意思是说:编译Redis时,可以通过“MALLOC”环境变量来为Redis指定一个非默认的内存分配器。而Redis默认反对使用“libc malloc”,在Linux系统中默认使用“jemalloc”。原因是“jemalloc”已经被证实比“libc”有更少的分片问题。