《Redis官方文档》Redis调试指南
《Redis官方文档》Redis调试指南
原文链接 译者:Adeline
Redis开发过程中十分注重其稳定性:我们尽一切努力来保证每一个版本的稳定,不出现突然崩溃等情况。但是即使在我们百分百的努力下,仍然没办法保证百分百的无bug。
Redis出现崩溃时,会生成一个详细的报告来描述当时的情景,但是有时候只看报告还不够,而且Redis的核心开发团队可能也没办法独立重现你出现崩溃时候的场景:在这种情况下,我们需要用户能够重现这个情景来帮助我们。
这个指南讲解了如何使用GDB来获得Redis开发者可能用到的信息。
GDB是什么?
GDB是一款GNU调试器:一个可以查看到其他程序内部状态的程序。通常来讲,跟踪和修正bug其实就是一个收集更多的bug出现时的信息的过程,所以GDB是一个极为有用的工具。
GDB有以下两种使用模式:
- 可以连接到一个运行的程序上来观察程序正在运行时候的状态
- 可以观察已经结束运行的程序的状态,使用程序运行时候的内存镜像,叫做核心文件(core file)来实现。
从调试Redis的bug的角度来看,我们需要用到GDB的这两种模式:用户可以通过把GDB连接到Redis实例上来重现bug出现时候的场景,当崩溃发生时,用户可以创建core file来给Redis开发人员,开发人员可以用它来查看崩溃发生时Redis的内部运行状态。
这种方法使得开发人员可以独立在自己的电脑上进行模拟和跟踪,不需要用户的配合,也就不需要用户在生产环境中为了配合调试来进行Redis的重启了。
不使用优化选项编译Redis
默认情况下,Redis是使用 -O2选项编译的(译者注:-O2是gcc编译时的优化选项),这表示编译器优化是启动的。这使得Redis运行更快,但同时也使得Redis(与其他程序一样)更难被GDB观测。
使用GDB连接时,最好使用make noopt命令来编译Redis,使其不进行编译优化(而不是仅仅使用make)。但是如果你已经在生产环境中使用了Redis,而且重新编译可能会带来一些问题和麻烦的话,就没有必要重新编译了。尽管是会有一些限制,但是对于使用优化选项编译的程序,GDB也是可以用的。
如果你能在第一次出现崩溃后就把Redis不使用优化的重新编译一下,那是极好的,因为下次出现问题的时候就很好跟踪了。
你不用担心不使用优化编译对性能的影响,因为Redis并非计算密集型(CPU-bound)软件(更偏向I/O密集型),这点小的影响很难在你的环境中构成问题。
把GDB连接到一个运行的进程上
如果你有一个运行中的Redis 服务器,你可以把GDB连接到上面,如果Redis崩溃你既可以查看内部运行状态也可以创建一个core dump文件。
把GDB连接到Redis进程上不会对Redis的运行性能有影响,所以这不是一件危险的事,可以放心去做。
为了把GDB连接上去,首先要知道Redis实例的进程ID(进行的pid)。你可以使用 redis-cli轻松获取到:
$ redis-cli info | grep process_id process_id:58414
上面的例子中,进程ID是58414 。
- 登录到Redis服务器上
- (非强制但建议的步骤)使用screen 或者tmux 终端来保证ssh连接超时后GDB会话不会被关闭。如果不知道screen是什么,可以阅读这篇文章
- 使用如下命令将GDB连接到Redis服务器:
gdb <path-to-redis-executable> <pid> 例如:gdb /usr/local/bin/redis-server 58414
GDB会启动并连接到运行的服务器上,打印信息大致如下:
Reading symbols for shared libraries + done 0x00007fff8d4797e6 in epoll_wait () (gdb)
- 这时候GDB已经连接上了,但是Redis实例现在被GDB阻塞了。为了使Redis实例继续运行,只需要在GDB提示界面中输入continue,然后回车即可。
- 完成!现在你的Redis服务器已经连接了GDB,你可以等着下次崩溃啦:)
- 如果你是使用screen/tmux运行GDB的话,现在是时候把GDB的运行和screen/tmux会话分离开了(译者理解就是关闭会话不会影响程序运行的意思),使用Ctrl-a a 即可。
崩溃发生后
Redis的DEBUG SEGFAULT命令可以模拟段故障(也就是一个严重的意外崩溃(当然不要在真正的生产系统中这个命令哈),现在我要用这个命令来使Redis崩溃,看看GDB中都做了什么:
(gdb) continue
Continuing.
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0xffffffffffffffff
debugCommand (c=0x7ffc32005000) at debug.c:220
220 *((char*)-1) = ‘x';
如你所见,GDB检测到了Redis的崩溃,甚至显示除了出错的文件名和行号。这已经比Redis的崩溃跟踪报告要详细了(报告只包括函数名和二进制偏移)
获取堆栈跟踪
第一件事儿就是使用GDB获得全栈跟踪信息。这非常简单,使用bt 命令就可以(bt是backtrace的简写)
(gdb) bt #0 debugCommand (c=0x7ffc32005000) at debug.c:220 #1 0x000000010d246d63 in call (c=0x7ffc32005000) at redis.c:1163 #2 0x000000010d247290 in processCommand (c=0x7ffc32005000) at redis.c:1305 #3 0x000000010d251660 in processInputBuffer (c=0x7ffc32005000) at networking.c:959 #4 0x000000010d251872 in readQueryFromClient (el=0x0, fd=5, privdata=0x7fff76f1c0b0, mask=220924512) at networking.c:1021 #5 0x000000010d243523 in aeProcessEvents (eventLoop=0x7fff6ce408d0, flags=220829559) at ae.c:352 #6 0x000000010d24373b in aeMain (eventLoop=0x10d429ef0) at ae.c:397 #7 0x000000010d2494ff in main (argc=1, argv=0x10d2b2900) at redis.c:2046
获得栈跟踪信息后,我们还需要使用info registers 命令来获得处理器寄存器信息
(gdb) info registers rax 0x0 0 rbx 0x7ffc32005000 140721147367424 rcx 0x10d2b0a60 4515891808 rdx 0x7fff76f1c0b0 140735188943024 rsi 0x10d299777 4515796855 rdi 0x0 0 rbp 0x7fff6ce40730 0x7fff6ce40730 rsp 0x7fff6ce40650 0x7fff6ce40650 r8 0x4f26b3f7 1327936503 r9 0x7fff6ce40718 140735020271384 r10 0x81 129 r11 0x10d430398 4517462936 r12 0x4b7c04f8babc0 1327936503000000 r13 0x10d3350a0 4516434080 r14 0x10d42d9f0 4517452272 r15 0x10d430398 4517462936 rip 0x10d26cfd4 0x10d26cfd4 <debugCommand+68> eflags 0x10246 66118 cs 0x2b 43 ss 0x0 0 ds 0x0 0 es 0x0 0 fs 0x0 0 gs 0x0 0
请一定在bug报告中包括这两种信息。
获得核心文件(core file)
下一步就是生成core dump,这是运行的Redis 进程的内存镜像。使用gcore 命令来完成:
(gdb) gcore Saved corefile core.58414
有一点很重要,你需要知道这包含Redis实例崩溃时其中包含的所有数据:Redis开发者可以保证不会泄露这些数据,并且在调试结束后第一时间删除,但你还是需要知道发送的core file中包含你的数据。
如果你的数据中包含比较敏感的信息,我们建议您把dump文件直接发给Salvatore Sanfilippo(就是这个文档的作者),邮箱地址是antirez at gmail dot com
需要给开发人员发送的信息
现在你可以把所有的信息发送给Redis核心团队了,这些包括:
- 你正在使用的Redis可执行文件
- 使用bt命令导出的堆栈跟踪和寄存器dump
- 使用GDB生成的核心文件(core file)
- 操作系统信息,GCC版本,Redis版本
感谢
您的帮助对我们来说非常重要!有许多的问题只能用这种方式来跟踪,非常感谢!而且帮助我们进行调试你有可能获得摩卡咖啡壶的奖励哦(Redis Moka Award).
原创文章,转载请注明: 转载自并发编程网 – ifeve.com
本文链接地址: 《Redis官方文档》Redis调试指南