Redis确实能扛10W QPS但你3K就timeout了说明请求根本没到Redis是在连接这一步就卡住了。 先看客户端连接池配置 大部分timeout都是这个问题。你的连接池配了多少连接// Jedis举例 JedisPoolConfig config new JedisPoolConfig(); config.setMaxTotal(8);// 最大连接数默认8个 config.setMaxIdle(8); config.setMinIdle(0);每秒3K请求8个连接够吗算一下 假设一个请求耗时5ms一个连接每秒能处理200个请求1000ms / 5ms。8个连接每秒最多处理1600个请求。 3K请求来了1600个正常处理剩下1400个在队列里等。等不到连接就timeout。解决方法 config.setMaxTotal(50);// 加大连接数 config.setMaxIdle(50); config.setMinIdle(20);// 保持一定数量的空闲连接 具体要多少连接用公式估算 连接数 (QPS峰值 * 单个请求耗时)// 1000 3K QPS假设耗时5ms需要15个连接。考虑峰值和突发配30-50差不多。 检查连接超时配置 客户端创建连接的超时时间是多少JedisPool pool new JedisPool(config, redis-host, 6379, 2000);// 这个2000就是超时时间单位ms 默认2秒。网络不好或者Redis压力大的时候2秒建立不了连接就报timeout。 改大点 JedisPool pool new JedisPool(config, redis-host, 6379, 5000); // 5秒 但这只是治标。建立连接慢说明有别的问题。 看Redis服务端连接数 客户端想连但Redis拒绝了进Redis看看 redis-cli INFO clients connected_clients:4998 blocked_clients:0 connected_clients是当前连接数。再看maxclients CONFIG GET maxclients 1) maxclients 2) 10000 如果connected_clients接近maxclients新连接就进不来了。查一下是不是有连接泄漏没正常关闭# 看哪个客户端连接最多 CLIENT LIST | grep -c 192.168.1.10 如果某个应用连了几千个多半是没关闭。检查代码用完记得关 Jedis jedis pool.getResource(); try { // 操作Redis } finally { jedis.close(); // 别忘了这个 }或者用try-with-resources try (Jedis jedis pool.getResource()) { // 操作Redis } 检查服务器文件描述符 Linux上每个连接是一个文件描述符。Redis进程能打开多少文件# 查Redis进程的限制 cat /proc/$(pidof redis-server)/limits | grep open files Max open files 10240 10240 files 如果Redis的maxclients是10000但文件描述符只有10240扣掉Redis自己用的根本撑不到10000连接。改大点 # 编辑/etc/security/limits.conf * soft nofile 65535 * hard nofile 65535 # 重启Redis生效 systemctl restart redis网络层的坑TIME_WAIT 高并发下客户端可能遇到端口耗尽。 Linux客户端端口范围默认是 cat /proc/sys/net/ipv4/ip_local_port_range 32768 60999 大概28000个可用端口。 每个连接占一个端口连接关闭后进入TIME_WAIT状态默认等60秒才能复用。 如果你的应用频繁建连接、关连接没用连接池28000个端口很快用完新连接就报Cannot assign requested address。 看有多少TIME_WAIT netstat -an | grep TIME_WAIT | wc -l 如果上万就有问题。 解决方法1用连接池别频繁创建销毁连接。解决方法2优化内核参数快速回收TIME_WAIT # /etc/sysctl.conf net.ipv4.tcp_tw_reuse 1 net.ipv4.tcp_fin_timeout 30 # 生效 sysctl -p Redis慢查询导致的timeout 还有一种情况Redis性能没问题但有慢查询阻塞了。 Redis是单线程一个慢查询能把后面所有请求堵住。客户端等不到响应就timeout。 查慢查询日志 redis-cli SLOWLOG GET 10 如果看到KEYS *、HGETALL一个大Hash、SMEMBERS一个大Set这些都能卡几百毫秒。 找出慢查询对应的代码优化掉。 排查思路 遇到timeout先看日志报的是Connection timeout还是Read timeout。 Connection timeout是连不上多半是连接池配太小、Redis连接数满了、或者网络问题。 Read timeout是连上了但没响应一般是慢查询把Redis卡住了。 然后就是逐个排查 先打日志看连接池状态 logger.info(Active: {}, Idle: {}, pool.getNumActive(), pool.getNumIdle()); Active总是接近MaxTotal加大连接池。 连接池够用还timeout看Redis连接数 redis-cli INFO clients | grep connected_clients 几千个连接多半是泄漏了检查代码有没有忘记close。 连接数也正常看慢查询 redis-cli SLOWLOG GET 10 KEYS、HGETALL这些直接改掉。 还不行就看系统层面TIME_WAIT、文件描述符 netstat -an | grep TIME_WAIT | wc -l ulimit -n 基本上顺着这个思路查问题都能找到。补充一个坑 见过有人每次请求都new一个Jedis用完就关闭没用连接池。 // 别这么写 Jedis jedis new Jedis(localhost, 6379); jedis.get(key); jedis.close(); 高峰期每秒几千个连接创建和销毁TIME_WAIT直接飙到几万端口耗尽timeout报不停。 改成连接池问题就没了。 还有定时任务在Redis里跑KEYS *扫全部key几百万个key扫一遍要好几秒这期间所有请求都被阻塞。改成SCAN分批扫就行。 这些问题的根源都是把Redis当成了无限资源随便用。 连接是有限的端口是有限的Redis是单线程的。 连接池配够、用完关闭、别跑慢查询3K QPS轻轻松松。