以下是一个 Node.js 监听 Redis key 变化的完整示例,包含详细的配置和实现步骤:
一、环境准备
- 启用 Redis 键空间通知
编辑 redis.conf 并添加:
notify-keyspace-events "KEA" # 启用所有键空间和键事件通知
重启 Redis 或使用命令临时启用:
redis-cli config set notify-keyspace-events "KEA"
安装依赖
npm install ioredis
二、Node.js 监听脚本
const Redis = require('ioredis');
// 配置 Redis 连接
const redis = new Redis({
host: 'localhost', // Redis 服务器地址
port: 6379, // Redis 服务器端口
password: 'your-password' // 如果有密码
});
// 创建专用的订阅客户端(建议与主客户端分离)
const subscriber = new Redis({
host: 'localhost',
port: 6379,
password: 'your-password'
});
// 订阅所有 key 变化事件
async function subscribeToKeyEvents() {
try {
// 订阅键空间事件(格式:__keyspace@<db>__:<key>)
await subscriber.subscribe('__keyspace@0__:*');
// 订阅键事件事件(格式:__keyevent@<db>__:<event>)
await subscriber.subscribe('__keyevent@0__:set');
await subscriber.subscribe('__keyevent@0__:del');
console.log('已成功订阅 Redis key 变化事件');
} catch (error) {
console.error('订阅失败:', error);
}
}
// 处理接收到的事件
subscriber.on('message', (channel, message) => {
if (channel.startsWith('__keyspace@')) {
// 键空间事件:message 是事件类型(如 set、del)
const key = channel.split(':')[1];
console.log(`Key ${key} 发生变化: ${message}`);
handleKeyChange(key, message);
} else if (channel.startsWith('__keyevent@')) {
// 键事件事件:message 是 key 名称
const event = channel.split(':')[1];
console.log(`事件 ${event} 发生在 Key: ${message}`);
handleKeyEvent(message, event);
}
});
// 自定义处理函数 - 键变化
function handleKeyChange(key, event) {
switch (event) {
case 'set':
// 处理 key 设置事件
redis.get(key).then(value => {
console.log(`Key ${key} 的新值是: ${value}`);
});
break;
case 'del':
// 处理 key 删除事件
console.log(`Key ${key} 已被删除`);
break;
case 'expire':
// 处理 key 过期事件
console.log(`Key ${key} 已过期`);
break;
default:
console.log(`Key ${key} 的其他事件: ${event}`);
}
}
// 自定义处理函数 - 事件发生
function handleKeyEvent(key, event) {
console.log(`事件 ${event} 影响了 Key: ${key}`);
// 根据事件类型执行不同逻辑
}
// 启动订阅
subscribeToKeyEvents();
// 优雅退出
process.on('SIGINT', () => {
subscriber.quit();
redis.quit();
console.log('已断开 Redis 连接');
process.exit();
});
三、测试示例
运行脚本后,在 Redis 客户端执行以下命令测试:
# 设置 key redis-cli set user:1 "John Doe" # 删除 key redis-cli del user:1 # 设置带过期时间的 key redis-cli setex temp:key 60 "value"
Node.js 脚本将输出:
Key user:1 发生变化: set Key user:1 的新值是: John Doe 事件 set 发生在 Key: user:1 Key user:1 发生变化: del Key user:1 已被删除 事件 del 发生在 Key: user:1 Key temp:key 发生变化: set Key temp:key 的新值是: value 事件 set 发生在 Key: temp:key ...60秒后... Key temp:key 发生变化: expire Key temp:key 已过期 事件 expire 发生在 Key: temp:key
四、关键配置说明
- Redis 事件类型
KEA:启用所有键空间和键事件(生产环境建议按需启用,如Ex仅监听过期事件)- 常用事件:
set、del、expire、rename、hset等
- 订阅模式
__keyspace@<db>__:<key>:监听特定 key 的所有事件__keyspace@<db>__:*:监听所有 key 的所有事件__keyevent@<db>__:<event>:监听特定事件的所有 key
- 多数据库支持
- 将
0替换为实际数据库编号(如__keyspace@1__:*)
- 将
五、生产环境注意事项
- 性能影响
- 大量事件可能影响 Redis 性能,建议仅监听必要事件。
- 可靠性保障
- 使用
ioredis的自动重连机制(默认开启) - 添加事件处理的重试和幂等性
- 使用
- 安全配置
- 使用 Redis 密码和 TLS 加密
- 通过
max_connections限制连接数
- 监控与告警
- 监控 Redis 命令耗时和 CPU 使用率
- 设置事件处理超时告警