1.2 安装配置与单线程模型


文档摘要

1.2 安装配置与单线程模型 本节摘要:编译安装 Redis、改对生产必改的几个参数,并看清"单线程"的真实边界——命令执行单线程,IO 与落盘早已多线程化。这个边界直接决定后面所有性能话题的推理方式。 动手装一个 生产环境建议源码编译,版本选偶数稳定版(如 7.2、7.4): 返回 PONG 就说明服务活了。改配置建议单独拷一份再改,别直接改默认文件。 装完先跑一轮冒烟测试,把"装好了"变成"验证过": 本机压测十万级每秒是正常水位,低一个数量级先查是不是编译时缺优化参数、跑在了虚拟机的共享核上。CONFIG GET 的输出确认配置文件真的被读进去了——改了文件却忘了重启或忘了指定配置路径,是新手部署翻车的头两名。

1.2 安装配置与单线程模型

本节摘要:编译安装 Redis、改对生产必改的几个参数,并看清"单线程"的真实边界——命令执行单线程,IO 与落盘早已多线程化。这个边界直接决定后面所有性能话题的推理方式。

动手装一个

生产环境建议源码编译,版本选偶数稳定版(如 7.2、7.4):

wget https://download.redis.io/releases/redis-7.4.tar.gz tar xzf redis-7.4.tar.gz && cd redis-7.4 make -j4 && make install PREFIX=/usr/local/redis /usr/local/redis/bin/redis-server --port 6390 & /usr/local/redis/bin/redis-cli -p 6390 ping

返回 PONG 就说明服务活了。改配置建议单独拷一份再改,别直接改默认文件。

装完先跑一轮冒烟测试,把"装好了"变成"验证过":

redis-benchmark -p 6390 -t set,get -n 100000 -q # 十万次读写压测 SET: 112359.55 requests per second GET: 118483.44 requests per second redis-cli -p 6390 CONFIG GET maxmemory maxmemory-policy # 确认关键项生效 1) "maxmemory" 2) "4294967296" 3) "maxmemory-policy" 4) "allkeys-lru"

本机压测十万级每秒是正常水位,低一个数量级先查是不是编译时缺优化参数、跑在了虚拟机的共享核上。CONFIG GET 的输出确认配置文件真的被读进去了——改了文件却忘了重启或忘了指定配置路径,是新手部署翻车的头两名。

生产必改的五个参数

bind 0.0.0.0 # 按网卡收敛,别真写 0.0.0.0 上公网 port 6390 # 换掉默认端口,减少扫描噪音 requirepass 你的强密码 # 无密码等于裸奔,公网每小时都有扫描器 maxmemory 4gb # 必须设,否则内存吃到触发系统淘汰进程 maxmemory-policy allkeys-lru # 缓存场景常用,见第 5 章 appendonly yes # 开 AOF,重启不丢数据

前三个管安全,后三个管"内存在内存里怎么活、怎么不丢"。把默认值和修改理由并排放一起,更能看出风险在哪:

参数 出厂默认 建议值 不改的后果
bind 全网卡 内网地址 公网暴露,扫描器分钟级光顾
requirepass 强随机串 任何人可读写删
port 6379 自选 默认端口受定向扫描最多
maxmemory 0 不限 物理内存六到七成 吃光内存被系统杀进程
appendonly no yes 重启数据清零

装完的操作系统层还有两件事常被漏掉:文件句柄数要够(连接数加持久化文件,万级起步),透明大页要关——它会让 fork 后的写时复制以两兆为单位复制内存,第 6 章的快照内存峰值会被它成倍放大。前者在系统限制里调,后者在开机参数里关,都是一次配置长期受益的动作。

单线程的真相

"Redis 是单线程"这句话在 6.0 之后已经不准确。准确的版本是:命令执行器是单线程,其余环节各有多线程

一条命令的线程分工

一条命令的线程分工

为什么敢单线程还快?三个条件凑齐:内存操作本身纳秒到微秒级;单线程免去了锁与上下文切换;基于 epoll 的事件循环让一万条空闲连接也不占 CPU。瓶颈通常在内存容量和网络带宽,不在 CPU——所以多线程执行命令收益有限,反而破坏无锁这个大前提。

6.0 引入的 IO 线程容易和"多线程执行"混淆,值得单独说清:读请求、解析协议、写回响应这三步可以分给 IO 线程并行做,但命令的执行仍然汇聚回主线程排队。也就是说并行的是"搬运",串行的是"计算"——数据结构仍然只被一个线程碰,无锁前提完好无损。默认配置下 IO 线程是关着的,十万级每秒以下的中等负载开了收益也不明显;网卡的吞吐先到顶时再考虑开。

⚠️ 常见坑:单线程的反面是"一条慢命令阻塞所有客户端"。KEYS 在百万键的库里要跑数百毫秒,期间所有请求排队。生产环境用 SCAN 增量遍历,删除大集合用 UNLINK 异步删。

验证一下线程模型

# 服务端 redis-cli -p 6390 info threads # 模拟慢命令(仅测试环境!) redis-cli -p 6390 debug sleep 2 # 另一个终端在 sleep 期间发请求,会观察到请求被阻塞约 2 秒

这个实验比任何文档都直观:主线程睡了两秒,整个世界就停了两秒。

线程分工不靠背,用操作系统直接验证:

# 看服务进程一共开了几个线程 ps -T -p $(pidof redis-server) | wc -l 14 # 主线程之外:IO 线程若干、bio 后台线程若干,各司其职 ps -T -p $(pidof redis-server) | awk 'NR>1 {print $NF}' | sort | uniq -c

十几个线程跑在一个"单线程"服务里并不矛盾:bio 线程族负责慢速收尾——关闭文件描述符、异步刷 AOF、释放大对象的内存,它们处理的全是"不碰数据结构"的杂活。判断某个动作会不会阻塞主线程,标准就一条:这个动作要不要读写数据结构本身。要,就在主线程排队;不要,多半已被挪去后台。

顺带纠正一个反向误解:既然瓶颈不在 CPU,那监控里 CPU 单核打满要不要管?要。单核满通常意味着某条命令在空转、或包太大解析太慢,top 里看哪个核满,SLOWLOG 里看同期记录,两相对照基本能锁定元凶。这类停顿在第 8 章有专门工具接棒:LATENCY 框架把 command 事件的尖刺记下来,配合慢日志把"卡了多少、卡在哪条命令"一次查清。

本节要点回顾

  • 安装:源码编译,独立配置文件,版本选稳定偶数版
  • 五个必改参数:绑定地址、端口、密码、maxmemory、持久化开关
  • 单线程边界:命令执行单线程;IO 解析、刷盘、删除已多线程或子进程化
  • 快的三前提:内存、无锁、事件循环;瓶颈在内存与网络而非 CPU
  • 代价:任何慢命令都是全局停顿,KEYS 与同步大删除是头号违禁品

作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U