You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Redis DEL多键与管道:二者是否均为非阻塞?

批量删除Redis大量键的方案疑惑

我需要从Redis中批量删除大量键,且已掌握所有键名无需搜索,目前评估两种方案:

  • 使用传递多键的DEL命令:本地性能测试显示该方案比管道快近10倍,但担心DEL的原子性会阻塞Redis
  • 在单个管道中执行大量DEL命令:速度较慢,但认为管道会逐行执行,不会阻塞其他客户端

我不确定多键DEL是否会阻塞至所有键删除完成,实际测试结果却显示它并未阻塞,这与Redis文档描述矛盾。

测试代码

let data = await setSomeDataInRedis();
let keys = data.map(([k]) => k);
const startDel = Date.now();

console.log('\n== del[] ==')
// Sending 3 request using 2 connections to Redis in parallel.
// Well, almost in parallel 'cause it's Node.js and also network is serial.
await Promise.all([
  redisClient1.hmget(['always-there', 'name']) // I expect this one returns 1st as it comes before DEL
    .then((r) => console.log(`get-before-del[] - ${Date.now() - startDel}ms - ${JSON.stringify(r)}`)),
  redisClient2.del(keys)                       // I expect this one returns 2nd and block 3rd on Redis side
    .then(() => console.log(`del[] - ${Date.now() - startDel}ms`)),
  redisClient1.hmget(['always-there', 'name']) // I expect this one returns 3rd because 2nd blocks Redis
    .then((r) => console.log(`get-after-del[] - ${Date.now() - startDel}ms - ${JSON.stringify(r)}`)),
])

console.log('\n== pipeline ==')
// Same here - sending 3 request using 2 connections to Redis in parallel.
data = await setSomeDataInRedis();
const pipeline = redisClient2.pipeline();
data.forEach(([k]) => pipeline.del(k));
const startPipe = Date.now();
await Promise.all([
  redisClient1.hmget(['always-there', 'name']) // I expect this one returns 1st as it comes before DEL
    .then((r) => console.log(`get-before-pipeline - ${Date.now() - startPipe}ms - ${JSON.stringify(r)}`)),
  pipeline.exec()                              // I expect this one returns 3rd as it has lots of commands, but non-blocking
    .then(() => console.log(`pipeline - ${Date.now() - startPipe}ms`)),
  redisClient1.hmget(['always-there', 'name']) // I expect this one returns 2nd as pipeline is non-blocking
    .then((r) => console.log(`get-after-pipeline - ${Date.now() - startPipe}ms - ${JSON.stringify(r)}`)),
])

console.log('\n== unlink[] ==')
data = await setSomeDataInRedis();
keys = data.map(([k]) => k);
const startUnlink = Date.now();
await Promise.all([
  redisClient1.hmget('always-there', 'name')
    .then((r) => console.log(`get before unlink[] - ${Date.now() - startUnlink}ms - ${JSON.stringify(r)}`)),
  redisClient2.unlink(keys)
    .then(() => console.log(`unlink[] - ${Date.now() - startUnlink}ms`)),
  redisClient1.hmget(['always-there', 'name'])
    .then((r) => console.log(`get after unlink[] - ${Date.now() - startUnlink}ms - ${JSON.stringify(r)}`)),
])

测试输出

== del[] ==
get-before-del[] - 62ms - ["name0.06551250522960261"]
get-after-del[] - 64ms - ["name0.06551250522960261"]
del[] - 183ms

== pipeline ==
get-before-pipeline - 127ms - ["name0.9763696909778301"]
get-after-pipeline - 131ms - ["name0.9763696909778301"]
pipeline - 1325ms

== unlink[] ==
get before unlink[] - 41ms - ["name0.25533683439953236"]
get after unlink[] - 47ms - ["name0.25533683439953236"]
unlink[] - 153ms

get-after-del[]早于del[]返回的现象似乎表明多键DEL是非阻塞的(非原子性),但这与Redis文档描述矛盾。

补充说明:最初未加入Unlink测试,虽其速度快10-20%,但仍会阻塞Redis,故补充相关测试。


内容的提问来源于stack exchange,提问作者Viktor Molokostov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 23:35:21