redis相关概念解释

✅ 问题 1

我的 Redis 已经部署,我的 微服务创建连接就算一个连接吗?

微服务 什么时候算创建了一个 Redis 连接?Redis 会做什么?

一句话先回答你:

👉 是的,微服务只要 connect 成功,就算一个 Redis 连接

👉 Redis 会为这个连接创建一个 client 对象,并把 socket 纳入 epoll 监听


一、从"微服务侧"看:什么时候叫"创建连接"

1️⃣ 微服务什么时候会创建 Redis 连接?

通常是这几种时机之一:

  • 应用启动
    • Spring Bean 初始化
    • RedisTemplate / Redisson 初始化
  • 第一次访问 Redis
    • 懒加载连接
  • 连接池预热
    • 一次性建多个连接

2️⃣ 本质动作只有一个(非常关键)

无论你用的是:

  • Jedis
  • Lettuce
  • Redisson

最终都会执行一个 TCP connect

bash 复制代码
微服务 ---> Redis TCP 三次握手

TCP 三次握手完成 = Redis 认为这是一个连接


二、从 Redis 视角:一个连接发生时 Redis 做了什么?

当你的微服务完成 TCP 三次握手时:

① Redis accept() 连接
cpp 复制代码
conn_fd = accept(listen_fd)
② Redis 创建一个 client 结构体

你可以把它理解为:

bash 复制代码
client { socket_fd 输入缓冲区 输出缓冲区 状态信息 }

每一个连接 = Redis 内存里的一个 client 对象


③ Redis 把这个 socket 注册进 epoll
bash 复制代码
epoll_ctl(epfd, ADD, socket_fd, READ)

意思是:

"这个连接以后 只要有数据进来,你通知我"

👉 到这一步,这个连接正式进入 Redis 的 IO 多路复用体系


三、微服务什么时候"发信号"?Redis 什么时候工作?

✅ Redis 不会主动找客户端

✅ Redis 只响应客户端事件

常见触发点:

微服务行为 Redis 感知到什么
发送命令 socket 变为 可读
客户端断连 socket 关闭事件
Redis 写响应 socket 可写

四、总结问题 1(你可以直接记)

TCP 建立成功 = 一个 Redis 连接

一个连接 = Redis 一个 client 对象

每个 client 都被 epoll 监听

客户端发数据,Redis 才会行动


✅ 问题 2

"一个线程,同时监听多个 IO 连接"

这个线程 Redis 启动就有吗?什么时候消失?

一句话回答你:

👉 是的,Redis 启动时就创建了这个线程 👉 Redis 进程不退出,这个线程永远不会消失


一、Redis 启动时究竟创建了什么线程?

Redis 主线程 ✅(你问的就是它)

  • 唯一
  • 贯穿 Redis 生命周期
  • 负责:
    • epoll 监听
    • 读取请求
    • 执行命令
    • 写回响应

👉 这就是:

"一个线程监听多个 IO 连接"里的那个线程


二、这个线程在干什么?(事件循环)

Redis 的主线程本质是一个 死循环

cpp 复制代码
while (!server.shutdown) { epoll_wait(); 处理就绪 socket; 执行命令; }

🧠 你可以理解为:

Redis 一直在说:
"谁有事?谁有事?"


三、这个线程什么时候会"消失"?

只有一种情况

情况 结果
Redis 正常运行 不消失
Redis 崩溃 / stop 线程结束
kill -9 进程直接没了

连接断开不会销毁这个线程

空闲不会销毁这个线程


四、Redis 为什么不为每个连接创建线程?

👉 如果这样:

  • 10 万连接
  • 10 万线程
  • 频繁上下文切换

✅ Redis 的选择是:

宁愿监听,不等待


✅ 问题 2 核心总结

✅ 这个线程 Redis 启动时就存在

✅ 它是 Redis 的 心跳

✅ 它不随连接变化

✅ 它挂了,Redis 就挂了


✅ 问题 3(最重要)

从 "部署 Redis → 连接 → epoll → 使用"

每一步 Redis 都在干什么?

下面是 完整真实时间线


🔹 第一阶段:Redis 启动(此时还没客户端)

1️⃣ 创建监听 socket

cpp 复制代码
listen_fd = socket() bind() listen()

✅ 等客户端来连


2️⃣ 创建 epoll 实例

cpp 复制代码
epfd = epoll_create()

3️⃣ 把 listen_fd 加入 epoll

cpp 复制代码
epoll_ctl(epfd, ADD, listen_fd, READ)

意思是:

"有客户端来连我时,叫醒我"


4️⃣ 进入主事件循环

cpp 复制代码
while(true) { epoll_wait() }

✅ 此刻 Redis 空转但不耗 CPU


🔹 第二阶段:微服务启动,连接 Redis

1️⃣ 客户端发起 TCP 连接

bash 复制代码
CONNECT redis:6379

2️⃣ 内核通知 epoll:listen_fd 可读

✅ epoll_wait 返回


3️⃣ Redis accept 连接

cpp 复制代码
conn_fd = accept()

4️⃣ Redis 创建 client 对象

  • 分配内存
  • 初始化 buffer
  • 绑定 socket_fd

5️⃣ Redis 注册 client socket 到 epoll

cpp 复制代码
epoll_ctl(epfd, ADD, conn_fd, READ)

✅ 等客户发命令


🔹 第三阶段:微服务发送 Redis 命令

1️⃣ 客户端发送数据

bash 复制代码
SET a 1

2️⃣ socket 变为可读

  • 数据进入内核 buffer
  • epoll 被唤醒

3️⃣ Redis read 数据

cpp 复制代码
read(conn_fd, input_buf)

4️⃣ Redis 解析命令(单线程)

bash 复制代码
SET a 1

5️⃣ Redis 执行命令(内存)

bash 复制代码
dict[a] = 1

✅ 无锁

✅ O(1)


6️⃣ Redis 写入输出缓冲区

bash 复制代码
+OK

7️⃣ epoll 监听可写事件

cpp 复制代码
epoll_ctl(MOD, conn_fd, WRITE)

8️⃣ 数据写回客户端

cpp 复制代码
write(conn_fd)

🔹 第四阶段:连接空闲 / 断开

空闲

  • Redis 不管
  • epoll 继续监听

客户端关闭

  • socket 关闭
  • epoll 收到事件
  • Redis 回收 client 对象
  • 释放内存

✅ 最终"全景一句话"(非常重要)

Redis 在启动时就创建 epoll 和主线程,

所有客户端连接只是被 登记监听
谁先准备好,主线程就处理谁,永不等待。

相关推荐
MC皮蛋侠客11 小时前
Redis 系列(一):全景与最小闭环——从 `SET` 命令到内存数据结构
数据结构·数据库·redis
渣渣盟15 小时前
当 Redis 写入成为性能瓶颈时,如何利用 异步批量 Sink 将吞吐量从 1w QPS 提升到 10w+?
数据库·redis·php
MC皮蛋侠客17 小时前
Redis 系列(六):过期、内存淘汰与内存优化——让 Redis 活得更久
数据库·redis·bootstrap
MC皮蛋侠客19 小时前
Redis 系列(七):事务、Pipeline 与 Lua 脚本——从原子性到 Functions
数据库·redis·lua
MC皮蛋侠客19 小时前
Redis 系列(八):缓存设计模式与一致性——从 Cache Aside 到防雪崩
redis·缓存·设计模式
渣渣盟20 小时前
当 Redis 写入不再是瓶颈后,Flink 任务的反压可能来自哪里?如何系统性地定位和解决 Flink 反压问题?
数据库·redis·flink
仍然.20 小时前
服务端高并发分布式结构演进之路
大数据·数据库·redis
MC皮蛋侠客20 小时前
Redis 系列(三):底层实现(一)——对象系统、SDS 与 dict
数据库·redis·缓存
渣渣盟21 小时前
当 Redis 集群发生主从切换(Failover)时,Flink 任务会崩溃吗?如何利用 Sentinel 实现高可用?
redis·flink·sentinel
海上小飞龙1 天前
Redis 分布式锁原理:从 SET NX EX 到 Redisson 看门狗
数据库·redis·分布式