
使用 ioredis 频繁读取 100kb 级 redis 字符串时出现逐次增长的延迟,并非 redis 服务端性能退化,而是客户端 javascript 单线程模型下 promise 并发调度与日志竞争导致的测量假象。
使用 ioredis 频繁读取 100kb 级 redis 字符串时出现逐次增长的延迟,并非 redis 服务端性能退化,而是客户端 javascript 单线程模型下 promise 并发调度与日志竞争导致的测量假象。
在您提供的脚本中,看似是“循环 200 次、每次发起一次 GET 并立即记录耗时”,实则执行的是并发发起 200 个异步请求 + 异步回调日志输出。关键问题在于:
-
for循环本身不等待.then()执行完成,所有con.get(key)几乎瞬间发出,形成高并发请求队列; - Redis 服务端响应基本是并行且稳定的(可通过
redis-benchmark验证),但 Node.js 主线程需串行处理每个.then()回调:解析响应、执行console.log、格式化字符串、写入 stdout——这些操作在单线程下会排队; - 更重要的是:
Date.now()在请求发出时打点(t1),但t2是在回调中获取的——而此时该回调可能已在事件队列中等待了数十毫秒(因前序回调尚未执行完),导致t2 - t1反映的并非网络+Redis处理时间,而是 “请求发出时间”到“回调实际执行时间” 的总延迟,其中包含大量事件循环排队开销。
✅ 验证方式:用 redis-benchmark 直接压测 Redis 服务端,可排除服务端瓶颈:
# 存入大值(约14MB) redis-cli -x set test-key <p>结果表明 Redis 响应稳定在毫秒级,无累积延迟。</p><p>? 正确的基准测试写法(顺序执行,准确测量单次耗时):</p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill3464" title="Redis Skill - 高性能缓存管理"><img src="https://img.php.cn/upload/skill/000/000/081/178960683454849.jpg" alt="Redis Skill - 高性能缓存管理" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/xiazai/skill3464" title="Redis Skill - 高性能缓存管理" class="overflowclass">Redis Skill - 高性能缓存管理</a> <p class="overflowclass">Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。</p> </div> <a rel="nofollow" href="/xiazai/skill3464" title="Redis Skill - 高性能缓存管理" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div><pre class="brush:php;toolbar:false;">for (let i = 0; i <p>⚠️ 注意事项:</p>
-
console.log本身有性能开销,高频调用会加剧主线程阻塞;生产环境压测建议用process.hrtime.bigint()+ 写入文件替代console.log; - 若业务确实需要高并发读取大值,应评估是否可拆分数据、启用压缩(如
redis-json或客户端 gzip)、或改用流式读取(如getBuffer()避免 UTF-8 解码开销); - ioredis 默认对大字符串做 UTF-8 解码,若值为二进制内容,务必使用
con.getBuffer(key)获取Buffer,避免解码瓶颈。
总结:观测到的“延迟递增”是客户端事件循环调度失真所致,而非 Redis 性能劣化。优化方向始终围绕——准确测量(await 串行)、减少主线程负载(避免高频 console)、适配数据形态(Buffer vs string)——三者协同,方能释放 Redis 的真实吞吐能力。










