《Redis官方文档》Redis调试指南
原文鏈接? ? ? 譯者:Adeline
Redis開發(fā)過程中十分注重其穩(wěn)定性:我們盡一切努力來保證每一個版本的穩(wěn)定,不出現(xiàn)突然崩潰等情況。但是即使在我們百分百的努力下,仍然沒辦法保證百分百的無bug。
Redis出現(xiàn)崩潰時,會生成一個詳細的報告來描述當時的情景,但是有時候只看報告還不夠,而且Redis的核心開發(fā)團隊可能也沒辦法獨立重現(xiàn)你出現(xiàn)崩潰時候的場景:在這種情況下,我們需要用戶能夠重現(xiàn)這個情景來幫助我們。
這個指南講解了如何使用GDB來獲得Redis開發(fā)者可能用到的信息。
GDB是什么?
GDB是一款GNU調試器:一個可以查看到其他程序內(nèi)部狀態(tài)的程序。通常來講,跟蹤和修正bug其實就是一個收集更多的bug出現(xiàn)時的信息的過程,所以GDB是一個極為有用的工具。
GDB有以下兩種使用模式:
- 可以連接到一個運行的程序上來觀察程序正在運行時候的狀態(tài)
- 可以觀察已經(jīng)結束運行的程序的狀態(tài),使用程序運行時候的內(nèi)存鏡像,叫做核心文件(core file)來實現(xiàn)。
從調試Redis的bug的角度來看,我們需要用到GDB的這兩種模式:用戶可以通過把GDB連接到Redis實例上來重現(xiàn)bug出現(xiàn)時候的場景,當崩潰發(fā)生時,用戶可以創(chuàng)建core file來給Redis開發(fā)人員,開發(fā)人員可以用它來查看崩潰發(fā)生時Redis的內(nèi)部運行狀態(tài)。
這種方法使得開發(fā)人員可以獨立在自己的電腦上進行模擬和跟蹤,不需要用戶的配合,也就不需要用戶在生產(chǎn)環(huán)境中為了配合調試來進行Redis的重啟了。
不使用優(yōu)化選項編譯Redis
默認情況下,Redis是使用 -O2選項編譯的(譯者注:-O2是gcc編譯時的優(yōu)化選項),這表示編譯器優(yōu)化是啟動的。這使得Redis運行更快,但同時也使得Redis(與其他程序一樣)更難被GDB觀測。
使用GDB連接時,最好使用make noopt命令來編譯Redis,使其不進行編譯優(yōu)化(而不是僅僅使用make)。但是如果你已經(jīng)在生產(chǎn)環(huán)境中使用了Redis,而且重新編譯可能會帶來一些問題和麻煩的話,就沒有必要重新編譯了。盡管是會有一些限制,但是對于使用優(yōu)化選項編譯的程序,GDB也是可以用的。
如果你能在第一次出現(xiàn)崩潰后就把Redis不使用優(yōu)化的重新編譯一下,那是極好的,因為下次出現(xiàn)問題的時候就很好跟蹤了。
你不用擔心不使用優(yōu)化編譯對性能的影響,因為Redis并非計算密集型(CPU-bound)軟件(更偏向I/O密集型),這點小的影響很難在你的環(huán)境中構成問題。
把GDB連接到一個運行的進程上
如果你有一個運行中的Redis 服務器,你可以把GDB連接到上面,如果Redis崩潰你既可以查看內(nèi)部運行狀態(tài)也可以創(chuàng)建一個core dump文件。
把GDB連接到Redis進程上不會對Redis的運行性能有影響,所以這不是一件危險的事,可以放心去做。
為了把GDB連接上去,首先要知道Redis實例的進程ID(進行的pid)。你可以使用?redis-cli輕松獲取到:
上面的例子中,進程ID是58414 。
- 登錄到Redis服務器上
- (非強制但建議的步驟)使用screen? 或者tmux?終端來保證ssh連接超時后GDB會話不會被關閉。如果不知道screen是什么,可以閱讀這篇文章
- 使用如下命令將GDB連接到Redis服務器:
-
gdb <path-to-redis-executable> <pid> 例如:gdb /usr/local/bin/redis-server 58414
GDB會啟動并連接到運行的服務器上,打印信息大致如下:
- 這時候GDB已經(jīng)連接上了,但是Redis實例現(xiàn)在被GDB阻塞了。為了使Redis實例繼續(xù)運行,只需要在GDB提示界面中輸入continue,然后回車即可。
- 完成!現(xiàn)在你的Redis服務器已經(jīng)連接了GDB,你可以等著下次崩潰啦:)
- 如果你是使用screen/tmux運行GDB的話,現(xiàn)在是時候把GDB的運行和screen/tmux會話分離開了(譯者理解就是關閉會話不會影響程序運行的意思),使用Ctrl-a a?即可。
崩潰發(fā)生后
Redis的DEBUG SEGFAULT命令可以模擬段故障(也就是一個嚴重的意外崩潰(當然不要在真正的生產(chǎn)系統(tǒng)中這個命令哈),現(xiàn)在我要用這個命令來使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的崩潰,甚至顯示除了出錯的文件名和行號。這已經(jīng)比Redis的崩潰跟蹤報告要詳細了(報告只包括函數(shù)名和二進制偏移)
獲取堆棧跟蹤
第一件事兒就是使用GDB獲得全棧跟蹤信息。這非常簡單,使用bt?命令就可以(bt是backtrace的簡寫)
請一定在bug報告中包括這兩種信息。
獲得核心文件(core file)
下一步就是生成core dump,這是運行的Redis 進程的內(nèi)存鏡像。使用gcore?命令來完成:
有一點很重要,你需要知道這包含Redis實例崩潰時其中包含的所有數(shù)據(jù):Redis開發(fā)者可以保證不會泄露這些數(shù)據(jù),并且在調試結束后第一時間刪除,但你還是需要知道發(fā)送的core file中包含你的數(shù)據(jù)。
如果你的數(shù)據(jù)中包含比較敏感的信息,我們建議您把dump文件直接發(fā)給Salvatore Sanfilippo(就是這個文檔的作者),郵箱地址是antirez at gmail dot com
需要給開發(fā)人員發(fā)送的信息
現(xiàn)在你可以把所有的信息發(fā)送給Redis核心團隊了,這些包括:
- 你正在使用的Redis可執(zhí)行文件
- 使用bt命令導出的堆棧跟蹤和寄存器dump
- 使用GDB生成的核心文件(core file)
- 操作系統(tǒng)信息,GCC版本,Redis版本
感謝
您的幫助對我們來說非常重要!有許多的問題只能用這種方式來跟蹤,非常感謝!而且?guī)椭覀冞M行調試你有可能獲得摩卡咖啡壺的獎勵哦(Redis Moka Award).?
總結
以上是生活随笔為你收集整理的《Redis官方文档》Redis调试指南的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: lxml学习【未完成】
- 下一篇: Delphi中字符串比较大小 VS Or