《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調試指南