linux上用gdb调试redis源码

最近为了对比传统分布式解决方案与区块链的解决方案的实际不同对比其不同和优缺点,便从redis的sentinel和cluster的解决方案入手来看,在查完官网和书中对redis模型的看基本描述后,其实最好的办法还是调试一下实际的代码,redis是用c实现,本地机器是windows的,又没有安装c的ide,且仅仅是调试用,所以就参考官网的调试的方法Redis debugging guide本着简单的方式来调试代码。
首先在windows上安装一个ubuntu的子系统,以后方便在这个系统上调试和部署其他linux的代码。如何安装子系统请自行百度。打开ubuntu的终端操作如下:

安装redis

先下载redis的源码并安装可直接参考官网: redis quickstart

wget http://download.redis.io/redis-stable.tar.gz
tar xvzf redis-stable.tar.gz
cd redis-stable
make
sudo make install
## 测试redis是否安装成功
redis-server
## 出现如下即已安装成功
7854:C 03 Jul 17:54:03.179 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
7854:C 03 Jul 17:54:03.179 # Redis version=4.0.10, bits=64, commit=00000000, modified=0, pid=7854, just started
7854:C 03 Jul 17:54:03.180 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
7854:M 03 Jul 17:54:03.183 * Increased maximum number of open files to 10032 (it was originally set to 1024).
                _._
           _.-``__ ''-._
      _.-``    `.  `_.  ''-._           Redis 4.0.10 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._
 (    '      ,       .-`  | `,    )     Running in standalone mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
 |    `-._   `._    /     _.-'    |     PID: 7854
  `-._    `-._  `-./  _.-'    _.-'
 |`-._`-._    `-.__.-'    _.-'_.-'|
 |    `-._`-._        _.-'_.-'    |           http://redis.io
  `-._    `-._`-.__.-'_.-'    _.-'
 |`-._`-._    `-.__.-'    _.-'_.-'|
 |    `-._`-._        _.-'_.-'    |
  `-._    `-._`-.__.-'_.-'    _.-'
      `-._    `-.__.-'    _.-'
          `-._        _.-'
              `-.__.-'

7854:M 03 Jul 17:54:03.192 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
7854:M 03 Jul 17:54:03.193 # Server initialized
7854:M 03 Jul 17:54:03.194 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
7854:M 03 Jul 17:54:03.198 * DB loaded from disk: 0.000 seconds
7854:M 03 Jul 17:54:03.219 * Ready to accept connections

安装gdb

sudo apt-get install  gdb

使用gdb debug redis源码

## 为了调试,在编译redis的源码的时候需要带上参数
make CFLAGS="-g -O0" 
## 如果之前已经编译过的话,可以删掉makefile文件重新编译即可。
## 执行如下命令
gdb redis-server
## 即可进入gdb的模式 如下:
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from redis-server...done.
(gdb)
## 先设置一个断点,并运行至该点断的位置,gdb支持断点到方法,如下:断点在main方法、并运行至该断点。
(gdb) b main
Breakpoint 1 at 0x433700: file server.c, line 3704.
(gdb) r
Starting program: /usr/local/bin/redis-server
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, main (argc=1, argv=0x7ffffffee1b8) at server.c:3704
3704    int main(int argc, char **argv) {
(gdb)

至此已经进入了debug的模式,并且现在的停留在server.c的main方法中,为了看的更方便可以执行如下命令进入多窗口模式可以边看源码边调试,还有一些其他命令的用法可以参考 Debugging with GDBgdb 调试利器

## 进入多窗口模式
 (gdb) layout src
## 出现如下图的界面

《linux上用gdb调试redis源码》 image.png

## 简单调试的基本用法
## 进入下一步next简写n
(gdb) n
## 进入方法里面 step,如下进入就是setproctitle.c中的spt_init方法里
(gdb) step
spt_init (argc=1, argv=0x7ffffffee1b8) at setproctitle.c:153
## 打印当前的一些变量值
(gdb) p argc
$1 = 1
## 跳出当前方法
(gdb) finish
## 当然还有很多更高级的用法,自行参考官网,或者使用help命令查看一些说明,在或者google
(gdb) help

到此就是整个简单使用gdb来调试redis源码的基本流程。下面我们就用gdb来试着调试一下sentinel模式将运行的代码。

准备调试redis配置文件和启动命令

搭建sentinel的模型,目标3个sentinel,1个主服务器,2个从服务器。
详细搭建教程可参考:Replication

配置1主2从

## 配置一主两从的结构 创建一个配置文件夹
$ sudo mkdir /svr/redis_config
$ sudo cp /svr/redis-stable/redis.conf /svr/redis_config/redis_6379.conf
$ cd /svr/redis_config
$ sudo cp redis_6379.conf redis_6380.conf
$ sudo cp redis_6379.conf redis_6381.conf
$ sudo vim redis_6379.conf
$ sudo vim redis_6380.conf
$ sudo vim redis_6381.conf

分别修改端口号和pid文件名和后台进程启动

## 以6380文件为例,修改如下几个值
port 6380
daemonize yes
slaveof 127.0.0.1 6379
pidfile /var/run/redis_6380.pid
## 保存之后退出,依次修改另一个文件,启动redis实例
$ sudo redis-server /svr/redis_config/redis_6379.conf
$ sudo redis-server /svr/redis_config/redis_6380.conf
$ sudo redis-server /svr/redis_config/redis_6381.conf
## 另外一种配置的从库方法就是客户端连上从库之后发送如下命令即可
$ sudo redis-cli -p 6380
127.0.0.1:6380> slaveof 127.0.0.1 6379

至此redis的主从就搭建好了.可以通过redis-cli连接发送info命令查看服务器状态信息

搭建三个sentinel

更多的配置细节参考:官网topic之sentinel

## 拷贝sentinel文件
$ sudo cp /svr/redis-stable/sentinel.conf /svr/redis_config/sentinel_26379.conf
$ sudo cp /svr/redis-stable/sentinel.conf /svr/redis_config/sentinel_26380.conf
$ sudo cp /svr/redis-stable/sentinel.conf /svr/redis_config/sentinel_26381.conf
$ sudo vim /svr/redis_config/sentinel_26379.conf
## 同样修改配置如下内容,以26380为例,其中dir为工作路径,请在启动前请确保此文件夹存在。
## sentinel的myid在三个文件中请一定要配置不同,因为这个值代表这个sentinel的runid。配置监听的主服务器和选票的数量。
port 26380
daemonize yes
dir "/svr/redis_config/sentinel_26380/tmp"
sentinel myid 672268275d7a8a9809acaa83ecc4f63dce39fc5a
sentinel monitor mymaster 127.0.0.1 6379 2
## 保存退出后启动应用
$ sudo redis-sentinel /svr/redis_config/sentinel_26379.conf
$ sudo redis-sentinel /svr/redis_config/sentinel_26380.conf
$ sudo redis-sentinel /svr/redis_config/sentinel_26381.conf
## 也可以用sentinel模式,如:
$ sudo redis-server sentinel_26381.conf --sentinel

至此三个sentinel已经搭建好了

## 客户端连接查看sentinel是否已经相互连接,使用info命令便可以看到详细信息
$ sudo redis-cli -p 26379
127.0.0.1:26379> info
# Server
redis_version:4.0.10
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:564e829c2a2c36f6
redis_mode:sentinel
os:Linux 4.4.0-17134-Microsoft x86_64
arch_bits:64
multiplexing_api:epoll
atomicvar_api:atomic-builtin
gcc_version:5.4.0
process_id:8472
run_id:3d6ee9716c852c234bdb61515372046396adb0b9
tcp_port:26379
uptime_in_seconds:35
uptime_in_days:0
hz:11
lru_clock:3907301
executable:/svr/redis_config/redis-sentinel
config_file:/svr/redis_config/sentinel_26379.conf

# Clients
connected_clients:3
client_longest_output_list:0
client_biggest_input_buf:0
blocked_clients:0

# CPU
used_cpu_sys:0.02
used_cpu_user:0.02
used_cpu_sys_children:0.00
used_cpu_user_children:0.00

# Stats
total_connections_received:3
total_commands_processed:75
instantaneous_ops_per_sec:1
total_net_input_bytes:3904
total_net_output_bytes:484
instantaneous_input_kbps:0.02
instantaneous_output_kbps:0.01
rejected_connections:0
sync_full:0
sync_partial_ok:0
sync_partial_err:0
expired_keys:0
expired_stale_perc:0.00
expired_time_cap_reached_count:0
evicted_keys:0
keyspace_hits:0
keyspace_misses:0
pubsub_channels:0
pubsub_patterns:0
latest_fork_usec:0
migrate_cached_sockets:0
slave_expires_tracked_keys:0
active_defrag_hits:0
active_defrag_misses:0
active_defrag_key_hits:0
active_defrag_key_misses:0

# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=127.0.0.1:6379,slaves=2,sentinels=3

从最后一行我们可以看到整个网络架构已经建立好了。

## 也可以用如下命令查看sentinels 信息
127.0.0.1:26379> sentinel sentinels mymaster
1)  1) "name"
    2) "672268275d7a8a9809acaa83ecc4f63dce39fc5b"
    3) "ip"
    4) "127.0.0.1"
    5) "port"
    6) "26381"
    7) "runid"
    8) "672268275d7a8a9809acaa83ecc4f63dce39fc5b"
    9) "flags"
   10) "sentinel"
   11) "link-pending-commands"
   12) "0"
   13) "link-refcount"
   14) "1"
   15) "last-ping-sent"
   16) "0"
   17) "last-ok-ping-reply"
   18) "488"
   19) "last-ping-reply"
   20) "488"
   21) "down-after-milliseconds"
   22) "30000"
   23) "last-hello-message"
   24) "259"
   25) "voted-leader"
   26) "?"
   27) "voted-leader-epoch"
   28) "0"
2)  1) "name"
    2) "672268275d7a8a9809acaa83ecc4f63dce39fc5a"
    3) "ip"
    4) "127.0.0.1"
    5) "port"
    6) "26380"
    7) "runid"
    8) "672268275d7a8a9809acaa83ecc4f63dce39fc5a"
    9) "flags"
   10) "sentinel"
   11) "link-pending-commands"
   12) "0"
   13) "link-refcount"
   14) "1"
   15) "last-ping-sent"
   16) "0"
   17) "last-ok-ping-reply"
   18) "488"
   19) "last-ping-reply"
   20) "488"
   21) "down-after-milliseconds"
   22) "30000"
   23) "last-hello-message"
   24) "562"
   25) "voted-leader"
   26) "?"
   27) "voted-leader-epoch"
   28) "0"

调试sentinel的相关代码

结合前面简单的调试和sentinel的配置文件,我们可以使用gdb来启动一个sentinel从main方法来开始调试。

## 先关掉一个sentinel
$ ps -aux|grep redis
root      7995  0.0  0.0  45636  2356 ?        Ssl  Jul03   0:01 redis-server 127.0.0.1:6379
root      8046  0.0  0.0  45636  2096 ?        Ssl  Jul03   0:00 redis-server 127.0.0.1:6380
root      8054  0.0  0.0  45636  2092 ?        Ssl  Jul03   0:01 redis-server 127.0.0.1:6381
jane-zh+  8267  0.0  0.0  16224   260 tty3     S    Jul03   0:00 redis-cli -p 26379
root      8286  0.0  0.0  14892   576 tty4     S    Jul03   0:00 sudo redis-cli -p 26380
root      8287  0.0  0.0  16224   256 tty4     S    Jul03   0:00 redis-cli -p 26380
root      8472  0.0  0.0  43588  2800 ?        Ssl  00:05   0:00 redis-sentinel *:26379 [sentinel]
root      8478  0.0  0.0  43588  2704 ?        Ssl  00:05   0:00 redis-sentinel *:26380 [sentinel]
root      8484  0.0  0.0  43588  2720 ?        Ssl  00:05   0:00 redis-sentinel *:26381 [sentinel]
root      8488  0.0  0.0  14656  2120 tty2     S    00:05   0:00 sudo redis-cli -p 26379
root      8489  0.0  0.0  16224  1284 tty2     S    00:05   0:00 redis-cli -p 26379
jane-zh+  8491  0.0  0.0  12892  1112 tty5     S    00:18   0:00 grep --color=auto redis
$ sudo kill -9 8472
## 使用gdb启动redis-sentinel命令
$ sudo gdb redis-sentinel
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from redis-sentinel...done.
(gdb) b main
Breakpoint 1 at 0x433700: file server.c, line 3704.
(gdb) r /svr/redis_config/sentinel_26379.conf
Starting program: /usr/local/bin/redis-sentinel /svr/redis_config/sentinel_26379.conf
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, main (argc=2, argv=0x7ffffffee698) at server.c:3704
3704    int main(int argc, char **argv) {
(gdb) layout src

至此便可以愉快的开始从头调试sentinel的代码,调试步骤依然像前面简单介绍的一样。下篇便是开始总结redis的sentinel。

    原文作者:zs_jane
    原文地址: https://www.jianshu.com/p/692d1cd27e9b
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞