CppGuide社区 CppGuide社区
首页
  • 🔥最新谷歌C++风格指南(含C++17/20)
  • 🔥C++17详解
  • 🔥C++20完全指南
  • 🔥C++23快速入门
  • C++语言面试问题集锦
  • 🔥交易系统开发岗位求职与面试指南 (opens new window)
  • 第1章 高频C++11重难点知识解析
  • 第2章 Linux GDB高级调试指南
  • 第3章 C++多线程编程从入门到进阶
  • 第4章 C++网络编程重难点解析
  • 第5章 网络通信故障排查常用命令
  • 第6章 高性能网络通信协议设计精要
  • 第7章 高性能服务结构设计
  • 第8章 Redis网络通信模块源码分析
  • 第9章 后端服务重要模块设计探索
  • 🚀 全部章节.pdf 下载 (opens new window)
  • 源码分析系列

    • leveldb源码分析
    • libevent源码分析
    • Memcached源码分析
    • TeamTalk源码分析
    • 优质源码分享 (opens new window)
    • 🔥远程控制软件gh0st源码分析
  • 从零手写C++项目系列

    • 🔥C++游戏编程入门(零基础学C++)
    • 🔥使用C++17从零开发一个调试器 (opens new window)
    • 🔥使用C++20从零构建一个完整的低延迟交易系统 (opens new window)
    • 🔥使用C++从零写一个C语言编译器 (opens new window)
    • 🔥从零用C语言写一个Redis
  • 🔥Windows 10系统编程
  • 🔥Linux 5.x内核开发与调试 完全指南 (opens new window)
  • TCP源码实现超详细注释版.pdf (opens new window)
  • Go语言特性

    • Go系统接口编程
    • 高效Go并发编程
    • Go性能调优
    • Go项目架构设计
  • Go项目实战

    • 🔥使用Go从零开发一个数据库
    • 🔥使用Go从零开发一个编译器 (opens new window)
    • 🔥使用Go从零开发一个解释器 (opens new window)
    • 🔥使用Go从零开发一个解释器 (opens new window)
    • 🔥用Go从零写一个编排器(类Kubernetes) (opens new window)
Rust编程指南
  • SQL零基础指南
  • MySQL开发与调试指南
GitHub (opens new window)
首页
  • 🔥最新谷歌C++风格指南(含C++17/20)
  • 🔥C++17详解
  • 🔥C++20完全指南
  • 🔥C++23快速入门
  • C++语言面试问题集锦
  • 🔥交易系统开发岗位求职与面试指南 (opens new window)
  • 第1章 高频C++11重难点知识解析
  • 第2章 Linux GDB高级调试指南
  • 第3章 C++多线程编程从入门到进阶
  • 第4章 C++网络编程重难点解析
  • 第5章 网络通信故障排查常用命令
  • 第6章 高性能网络通信协议设计精要
  • 第7章 高性能服务结构设计
  • 第8章 Redis网络通信模块源码分析
  • 第9章 后端服务重要模块设计探索
  • 🚀 全部章节.pdf 下载 (opens new window)
  • 源码分析系列

    • leveldb源码分析
    • libevent源码分析
    • Memcached源码分析
    • TeamTalk源码分析
    • 优质源码分享 (opens new window)
    • 🔥远程控制软件gh0st源码分析
  • 从零手写C++项目系列

    • 🔥C++游戏编程入门(零基础学C++)
    • 🔥使用C++17从零开发一个调试器 (opens new window)
    • 🔥使用C++20从零构建一个完整的低延迟交易系统 (opens new window)
    • 🔥使用C++从零写一个C语言编译器 (opens new window)
    • 🔥从零用C语言写一个Redis
  • 🔥Windows 10系统编程
  • 🔥Linux 5.x内核开发与调试 完全指南 (opens new window)
  • TCP源码实现超详细注释版.pdf (opens new window)
  • Go语言特性

    • Go系统接口编程
    • 高效Go并发编程
    • Go性能调优
    • Go项目架构设计
  • Go项目实战

    • 🔥使用Go从零开发一个数据库
    • 🔥使用Go从零开发一个编译器 (opens new window)
    • 🔥使用Go从零开发一个解释器 (opens new window)
    • 🔥使用Go从零开发一个解释器 (opens new window)
    • 🔥用Go从零写一个编排器(类Kubernetes) (opens new window)
Rust编程指南
  • SQL零基础指南
  • MySQL开发与调试指南
GitHub (opens new window)
  • 第1章高频C++11重难点知识解析

  • 第2章Linux GDB高级调试指南

  • 第3章C++多线程编程从入门到进阶

  • 第4章C++网络编程重难点解析

  • 第5章网络通信故障排查常用命令

  • 第6章高性能网络通信协议设计精要

  • 第7章高性能服务结构设计

  • 第8章Redis 网络通信模块源码分析

    • 8.1 调试 redis 环境与准备工作
      • 8.2 探究redis-server端的网络通信模块
      • 8.3 探究 redis-cli 端的网络通信模型
      • 8.4 redis 的通信协议格式
      • 8.5 总结
    • 第9章后端服务重要模块设计探索

    • C++后端开发进阶
    • 第8章Redis 网络通信模块源码分析
    zhangxf
    2023-04-05
    目录

    8.1 调试 redis 环境与准备工作

    上一章节我们介绍了 one thread one loop 思想,redis 的网络通信结构就是以这一思想为蓝本的实例,本节我将详细介绍之,即以 redis 为例来讲解后端项目结构是怎样的。当然,本章介绍的角度与前面的章节思路不一样,前面的章节是先给结论,然后再加以论证,而本节则是假设预先不清楚 redis 网络通信层的结构,我们会以分析 redis 源码与 gdb 调试相结合的方式,来探究 redis 并逐步搞清楚 redis 的网络通信模块结构。

    # 8.1.1 我的编译和调试环境

    先来介绍一下探究 redis 的环境(我的环境):在 Linux 机器上调试,代码分析和阅读使用的是 Mac 机器上的 VSCode。

    • Linux 调试机器:CentOS 7.0,gdb 8.3
    • 代码阅读机器:macOS Catalina,VSCode 1.45.1
    • redis 版本:6.0.3(笔者成书时 redis 最新版本)

    # 8.1.2 redis 源码下载与编译

    下载最新的 redis 源码后解压并在 CentOS 系统中编译出带有调试符号可执行文件。

    由于不同版本的代码可能存在与本章节内容中的行号不完全匹配的情况,为了方便读者阅读本文时与源码相对应,这里提供两个 redis-6.0.3 版本下载地址:

    github:https://github.com/balloonwj/redis-6.0.3

    码云:https://gitee.com/balloonwj/redis-6.0.3

    利用 gdb 启动 redis-server,进入 redis-6.0.3/src,其中 redis-server 和 redis-cli 是我们需要调试的程序。用 gdb 关联 redis-server,并设置通过命令行设置 redis.conf 文件的路径,然后启动,操作如下:

    [root@myaliyun ~]# cd redis-6.0.3/src       
    [root@myaliyun src]# gdb redis-server 
    GNU gdb (GDB) 8.3
    Reading symbols from redis-server...
    (gdb) set args "../redis.conf"
    (gdb) run
    Starting program: /root/redis-6.0.3/src/redis-server "../redis.conf"
    [Thread debugging using libthread_db enabled]
    Using host libthread_db library "/usr/lib64/libthread_db.so.1".
    7470:C 10 Jun 2020 20:32:19.625 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
    7470:C 10 Jun 2020 20:32:19.625 # Redis version=6.0.3, bits=64, commit=00000000, modified=0, pid=7470, just started
    7470:C 10 Jun 2020 20:32:19.625 # Configuration loaded
                    _._                                                  
               _.-``__ ''-._                                             
          _.-``    `.  `_.  ''-._           Redis 6.0.3 (00000000/0) 64 bit
      .-`` .-```.  ```\/    _.,_ ''-._                                   
     (    '      ,       .-`  | `,    )     Running in standalone mode
     |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
     |    `-._   `._    /     _.-'    |     PID: 7470
      `-._    `-._  `-./  _.-'    _.-'                                   
     |`-._`-._    `-.__.-'    _.-'_.-'|                                  
     |    `-._`-._        _.-'_.-'    |           http://redis.io        
      `-._    `-._`-.__.-'_.-'    _.-'                                   
     |`-._`-._    `-.__.-'    _.-'_.-'|                                  
     |    `-._`-._        _.-'_.-'    |                                  
      `-._    `-._`-.__.-'_.-'    _.-'                                   
          `-._    `-.__.-'    _.-'                                       
              `-._        _.-'                                           
                  `-.__.-'                                               
    
    7470:M 10 Jun 2020 20:32:19.627 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
    7470:M 10 Jun 2020 20:32:19.627 # Server initialized
    7470:M 10 Jun 2020 20:32:19.627 # 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.
    7470:M 10 Jun 2020 20:32:19.627 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
    [New Thread 0x7ffff0bb9700 (LWP 7475)]
    [New Thread 0x7ffff03b8700 (LWP 7476)]
    [New Thread 0x7fffefbb7700 (LWP 7477)]
    [New Thread 0x7fffef3b6700 (LWP 7478)]
    [New Thread 0x7fffeebb5700 (LWP 7479)]
    [New Thread 0x7fffee3b4700 (LWP 7480)]
    7470:M 10 Jun 2020 20:32:19.634 * Ready to accept connections
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42

    以上是 redis-server 的启动成功后的画面。

    我们再开一个 session,再次进入 redis 源码所在的 src 目录,然后使用 gdb 启动 redis 客户端 redis-cli:

    [root@myaliyun src]# gdb redis-cli
    GNU gdb (GDB) 8.3
    Reading symbols from redis-cli...
    (gdb) r
    Starting program: /root/redis-6.0.3/src/redis-cli 
    [Thread debugging using libthread_db enabled]
    Using host libthread_db library "/usr/lib64/libthread_db.so.1".
    127.0.0.1:6379> 
    
    1
    2
    3
    4
    5
    6
    7
    8

    以上是 redis-cli 启动成功后的画面。

    # 8.1.3 通信示例与术语约定

    由于本章节的主要目的是为了学习和研究 redis 的网络通信模块,并不关心 redis 其他一些内容,因此为了方便说明问题,我们使用的一个简单的通信实例,即通过 redis-cli 产生一个 key 为 "hello",value 为 "world" 的 key-value 数据,然后得到 redis-server 的响应。我们通过这样一个实例来研究 redis 的网络通信模块。

    127.0.0.1:6379> set hello world
    OK
    127.0.0.1:6379> 
    
    1
    2
    3

    为了方便行文,我们先约定几个技术术语:

    • listenfd,即侦听 fd,指的是网络通信中作为服务器端的一方,用于绑定 ip 和端口号,并调用 listen 函数启动侦听操作的 socket 对象;
    • clientfd,即客户端 fd,指的是网络通信中作为服务器端的一方,调用 accept 函数接受连接返回的、与某路客户端连接对应的 socket;
    • connfd,指的是网络通信中作为客户端一方,创建后可以调用 connect 函数去连接服务器的 socket。

    Linux 系统上 socket 也是一种文件描述符(File Descriptor),因此也称之为 fd。

    上次更新: 2025/04/01, 20:53:14
    7.12 带有网络通信模块的服务器的经典结构
    8.2 探究redis-server端的网络通信模块

    ← 7.12 带有网络通信模块的服务器的经典结构 8.2 探究redis-server端的网络通信模块→

    最近更新
    01
    第二章 关键字static及其不同用法
    03-27
    02
    第一章 auto与类型推导
    03-27
    03
    C++语言面试问题集锦 目录与说明
    03-27
    更多文章>
    Copyright © 2024-2025 沪ICP备2023015129号 张小方 版权所有
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式