Redis 核心模块是单线程架构,其高效利用 epoll I/O 多路复用机制实现了单线程高并发。
但是 Redis 服务有很多模块,整体上来说是多线程的。
top -Hbn1 -p `pidof redis-server`
top -Hbn1 -p `pidof redis-server`
top - 16:37:13 up 2 days, 6:38, 5 users, load average: 0.10, 0.11, 0.17
Threads: 4 total, 0 running, 4 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni, 98.3 id, 1.7 wa, 0.0 hi, 0.0 si, 0.0 st
MiB Mem : 7869.6 total, 696.9 free, 2518.8 used, 4653.8 buff/cache
MiB Swap: 2048.0 total, 1016.4 free, 1031.6 used. 5004.1 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
697076 redis 20 0 49988 3348 1840 S 0.0 0.0 0:08.79 /usr/bin/redis-server 127.0.0.1:6379
697077 redis 20 0 49988 3348 1840 S 0.0 0.0 0:00.00 /usr/bin/redis-server 127.0.0.1:6379
697078 redis 20 0 49988 3348 1840 S 0.0 0.0 0:00.00 /usr/bin/redis-server 127.0.0.1:6379
697079 redis 20 0 49988 3348 1840 S 0.0 0.0 0:00.00 /usr/bin/redis-server 127.0.0.1:6379
ps -eLF | egrep "PID|redis-server" | grep -v grep
UID PID PPID LWP C NLWP SZ RSS PSR STIME TTY TIME CMD
redis 697076 1 697076 0 4 12497 3344 3 15:41 ? 00:00:16 /usr/bin/redis-server 127.0.0.1:6379
redis 697076 1 697077 0 4 12497 3344 1 15:41 ? 00:00:00 /usr/bin/redis-server 127.0.0.1:6379
redis 697076 1 697078 0 4 12497 3344 0 15:41 ? 00:00:00 /usr/bin/redis-server 127.0.0.1:6379
redis 697076 1 697079 0 4 12497 3344 1 15:41 ? 00:00:00 /usr/bin/redis-server 127.0.0.1:6379
采用单线程模型也和 Redis 业务有关,几乎是纯 IO 操作,只消耗内存和网络带宽,不需要太多 CPU 资源。
单线程更安全,更简单,维护起来成本低。多线程除了线程切换消耗和锁的消耗之外,还会引入执行顺序的不确定性,增加了系统复杂度。
Redis 6.0.0 开始(2020/05/01),Redis 在核心模块中使用多线程。
Ubuntu 官方源中的版本才 5.0.7,是享用不到了。
即便是 6.0+,多线程默认关闭(重点:为什么默认关闭?),据网上资料显示,需要配置相关参数:
# 默认为 1,就是和之前行为一致,主线程处理 IO
io-threads 4
# 如果 io-threads 大于 1,生成线程处理写操作,读操作继续在主线程处理
# 除非配置下面这行:
io-threads-do-read yes
PS:Redis 6.0 据说是 Redis 史上最大的一个发行版本,可能就是改多线程闹得。
改成多线程的原因:在一些复杂场景下,巨量 IO 操作(看这个默认配置,应该主要是写 Socket)也会导致 CPU 消耗太大,这种情况下,多线程带来的性能影响可以被忽略。
所以,Redis 新版允许 I/O 操作部分(包的读写和解析)改成多线程并行,数据访问部分维持单线程模型不变。
据说在一些基准测试中,开启多线程的 Redis 实例性能提升了一倍。
但是我想,可能绝大部分人不用关心这个变动。