# redis-keys-delete **Repository Path**: dbother/redis-keys-delete ## Basic Information - **Project Name**: redis-keys-delete - **Description**: Redis 批量 key 删除工具,支持 Standalone、Sentinel、Cluster 三种部署模式 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-01-19 - **Last Updated**: 2026-01-20 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Redis Keys Delete Go 安全的 Redis 批量 key 删除工具,支持 Standalone、Sentinel、Cluster 三种部署模式。 ## 特性 - **高性能** - 流式处理架构,内存占用极低(< 10MB),支持百万级 key 操作 - **安全可靠** - 白名单、dry-run、审计日志、DB 参数保护等多重安全机制 - **三种模式** - Export(导出)、Delete(从文件删除)、Direct(直接删除) - **数据恢复** - 支持导出 key-value 对,误删可恢复 - **多种部署** - 支持 Standalone、Sentinel、Cluster - **智能删除** - Cluster 模式自动计算 slot 并按批量删除,避免 CROSSSLOT 错误 - **错误追踪** - 详细的错误日志(`delete.err`),记录所有失败的 key 和原因 - **实时进度** - 动态显示操作进度,每批次实时更新 - **白名单机制** - 精确 key 和前缀白名单,支持引号处理特殊字符 - **安全保护** - 大 key 保护(`--max-value-size`),防止内存爆炸 ## 安装 ### 从源码编译 ```bash # 克隆仓库 git clone cd redis-keys-delete # 编译 go build -o redis-delete-go ./cmd/redis-delete # 或者使用 Makefile make build ``` ### 交叉编译 ```bash # Linux amd64 GOOS=linux GOARCH=amd64 go build -o redis-delete-go-linux-amd64 ./cmd/redis-delete # Linux arm64 GOOS=linux GOARCH=arm64 go build -o redis-delete-go-linux-arm64 ./cmd/redis-delete # macOS amd64 GOOS=darwin GOARCH=amd64 go build -o redis-delete-go-darwin-amd64 ./cmd/redis-delete # macOS arm64 (Apple Silicon) GOOS=darwin GOARCH=arm64 go build -o redis-delete-go-darwin-arm64 ./cmd/redis-delete ``` ## 快速开始 ### 推荐工作流程 ```bash # 1. 导出模式:扫描并保存到文件 ./redis-delete \ --mode cluster \ --host 10.10.2.12 \ --port 7001 \ --key-prefix "cache:" \ --export # 2. 审核导出的文件 cat work/keys_to_delete.txt # 3. 确认无误后删除 ./redis-delete \ --mode cluster \ --host 10.10.2.12 \ --port 7001 \ --del ``` ### 直接删除模式(谨慎使用) ```bash # 直接模式:扫描并立即删除(建议先用 --dry-run) ./redis-delete \ --mode cluster \ --host 10.10.2.12 \ --port 7001 \ --key-prefix "temp:" \ --direct --dry-run # 先预览 # 确认无误后去掉 --dry-run ./redis-delete \ --mode cluster \ --host 10.10.2.12 \ --port 7001 \ --key-prefix "temp:" \ --direct ``` ## 详细用法 ### 1️⃣ 单节点模式(Standalone) 适用于单机 Redis 或 Master-Slave 的 Master 节点。 ```bash # 导出特定前缀的 keys ./redis-delete \ --mode standalone \ --host 192.168.1.100 \ --port 6379 \ --password "your_password" \ --db 3 \ --key-prefix "session:" \ --export # 从文件删除 ./redis-delete \ --mode standalone \ --host 192.168.1.100 \ --port 6379 \ --password "your_password" \ --db 3 \ --del # 直接删除 ./redis-delete \ --mode standalone \ --host 192.168.1.100 \ --port 6379 \ --password "your_password" \ --db 3 \ --key-prefix "temp:" \ --direct ``` ### 2️⃣ 哨兵模式(Sentinel) 自动从 Sentinel 发现主节点并执行操作。 ```bash # 导出模式 ./redis-delete \ --mode sentinel \ --sentinel-host 192.168.1.200 \ --sentinel-port 26379 \ --sentinel-password "sentinel_password" \ --master-name mymaster \ --password "redis_password" \ --db 3 \ --key-prefix "cache:" \ --export # 删除模式 ./redis-delete \ --mode sentinel \ --sentinel-host 192.168.1.200 \ --sentinel-port 26379 \ --master-name mymaster \ --password "redis_password" \ --db 3 \ --del # 直接删除 ./redis-delete \ --mode sentinel \ --sentinel-host 192.168.1.200 \ --sentinel-port 26379 \ --master-name mymaster \ --password "redis_password" \ --key-prefix "expired:" \ --direct ``` ### 3️⃣ 集群模式(Cluster) 支持 Redis Cluster,自动按 slot 批量删除,避免 CROSSSLOT 错误。 **导出文件格式**:纯 key 列表(例如 `cache:user:1001`) ```bash # 导出模式 ./redis-delete \ --mode cluster \ --host 192.168.1.50 \ --port 7001 \ --password "cluster_password" \ --key-prefix "cache:" \ --export # 查看导出的 keys cat work/keys_to_delete.txt # 输出示例: # cache:user:1001 # cache:user:1002 # cache:session:abc # 删除模式(自动按 slot 批量删除) ./redis-delete \ --mode cluster \ --host 192.168.1.50 \ --port 7001 \ --password "cluster_password" \ --del # 直接删除 ./redis-delete \ --mode cluster \ --host 192.168.1.50 \ --port 7001 \ --password "cluster_password" \ --key-prefix "temp:" \ --direct ``` **手动指定集群节点**(可选): ```bash ./redis-delete \ --mode cluster \ --cluster-nodes "192.168.1.50:7001,192.168.1.51:7002,192.168.1.52:7003" \ --password "cluster_password" \ --key-prefix "cache:" \ --export ``` ## 导出与恢复 ### 导出模式选择 #### 1. 快速导出(默认)- 只导出 key **适用场景**:大多数场景(95%),不需要恢复功能 ```bash # 导出 key 列表(快速,不获取 value) ./redis-delete --host 127.0.0.1 --port 6379 --mode standalone \ --key-prefix "test:str:user:" --db 0 --export # 输出文件格式: # test:str:user:1 # test:str:user:2 # test:str:user:3 ``` **优点**: - ⚡ 速度快 10-100 倍(不获取 value) - 💾 内存占用极低(< 10MB,流式处理) - 📉 降低 Redis 压力(无 MGET 调用) - 🔒 更安全(无 value,适合敏感数据) #### 2. 完整导出 - 导出 key-value 对 **适用场景**:需要恢复能力时 ```bash # 导出 key-value 对(较慢,但可恢复) ./redis-delete --host 127.0.0.1 --port 6379 --mode standalone \ --key-prefix "test:" --db 0 --export --export-with-values # 输出文件格式: # test:key1 value1 # test:key2 value2 # test:key3 value3 ``` **安全保护**: 使用 `--max-value-size` 限制单个 value 大小,防止大 key 导致内存问题: ```bash # 限制 value 大小为 10MB(默认值) ./redis-delete --host 127.0.0.1 --port 6379 --mode standalone \ --key-prefix "test:" --db 0 --export --export-with-values \ --max-value-size 10MB # 不限制大小(谨慎使用) ./redis-delete --host 127.0.0.1 --port 6379 --mode standalone \ --key-prefix "test:" --db 0 --export --export-with-values \ --max-value-size 0 ``` **格式说明**: - `100` 或 `100b`:100 字节 - `10k` 或 `10KB`:10KB - `10m` 或 `10MB`:10MB(默认) - `1g` 或 `1GB`:1GB - `0` 或 `no-limit`:无限制 **注意**: - ⚠️ 只支持 string 类型的 key 完整恢复 - ⚠️ hash/list/set/zset 类型的 key 恢复后为 string 类型(空值) - ⚠️ 超过 `--max-value-size` 的 key 会被跳过并记录到日志 ### 数据恢复 如果使用 `--export-with-values` 导出了 key-value 对,误删后可以恢复: ```bash # 恢复模式(从 key-value 文件恢复) ./redis-delete --host 127.0.0.1 --port 6379 --mode standalone \ --db 0 --restore --restore-file work/keys_to_delete.txt # 输出: # ✅ Restore completed: 102 restored, 0 failed ``` **完整工作流程**: ```bash # 1. 导出(含 value) ./redis-delete --host 127.0.0.1 --port 6379 --mode standalone \ --key-prefix "test:" --db 0 --export --export-with-values # 2. 审核文件 cat work/keys_to_delete.txt # 3. 删除 ./redis-delete --host 127.0.0.1 --port 6379 --mode standalone \ --db 0 --del # 4. 如果误删,恢复 ./redis-delete --host 127.0.0.1 --port 6379 --mode standalone \ --db 0 --restore --restore-file work/keys_to_delete.txt ``` ## 白名单机制 保护特定的 key 不被导出/删除: ### 精确白名单 ```bash # 保护指定的 keys ./redis-delete --host 127.0.0.1 --port 6379 --mode standalone \ --key-prefix "test:str:user:" \ --whitelist-keys "test:str:user:96,test:str:user:97" \ --db 0 --export ``` ### 前缀白名单 ```bash # 保护指定前缀的所有 keys ./redis-delete --host 127.0.0.1 --port 6379 --mode standalone \ --key-prefix "test:" \ --whitelist-prefixes "test:important:,test:system:" \ --db 0 --export ``` ### 处理特殊字符 如果 key 中包含逗号、引号等特殊字符,使用引号包围: ```bash # key 中包含逗号 --whitelist-keys '"user:123,name:alice","user:456,data"' # key 中包含空格 --whitelist-keys '"key with spaces",normal_key' # 解析结果: # ["user:123,name:alice", "user:456,data", "key with spaces", "normal_key"] ``` ### 组合使用 ```bash # 前缀白名单 + 精确白名单 ./redis-delete \ --mode cluster \ --host 10.10.2.12 \ --port 7001 \ --key-prefix "cache:" \ --whitelist-prefixes "cache:important:,cache:system:" \ --whitelist-keys '"cache:special,key",cache:user:session:master"' \ --export ``` ## 安全特性 ### 1. Dry-run 模式 预览操作而不真正删除,强烈建议在生产环境使用前先 dry-run! **特点**: - 📋 只扫描和统计,不执行任何删除操作 - ⚡ **跳过速率限制**:dry-run 不受 `--batch-delay` 限制,快速完成预览 - 📊 显示将被删除的 key 数量 ```bash # Delete 模式 dry-run ./redis-delete \ --mode cluster \ --host 10.10.2.12 \ --port 7001 \ --del --dry-run # Direct 模式 dry-run ./redis-delete \ --mode cluster \ --host 10.10.2.12 \ --port 7001 \ --key-prefix "test:" \ --direct --dry-run ``` ### 2. 操作日志 所有操作都会记录日志,包括扫描、导出、删除的进度信息。 ```bash # 日志会输出到控制台 [2026-01-16 22:06:43.656] [INFO] Starting export mode... [2026-01-16 22:06:43.802] [INFO] Scanning keys with pattern: cache:* [2026-01-16 22:06:43.839] [INFO] ✅ Export completed: 9 keys written to work/keys_to_delete.txt ``` ### 3. 数据库参数保护(Standalone/Sentinel) 在 Standalone 和 Sentinel 模式下,**删除和恢复操作**必须显式指定 `--db` 参数,防止误删或误恢复默认的 DB 0。 ```bash # ❌ 错误:不指定 --db 参数 ./redis-delete --mode standalone --host 192.168.1.100 --port 6379 --del # Error: must explicitly specify --db parameter for delete/restore mode # ✅ 正确:明确指定数据库编号 ./redis-delete \ --mode standalone \ --host 192.168.1.100 \ --port 6379 \ --db 3 \ --del ``` **适用范围**: - ✅ Standalone/Sentinel 模式的删除操作(`--del`) - ✅ Standalone/Sentinel 模式的恢复操作(`--restore`) - ❌ Cluster 模式(不支持多数据库,不需要此参数) - ❌ Export/Direct 模式(不修改已有数据,不需要此保护) ### 4. 通配符安全 使用通配符导出/删除所有 keys 需要明确确认。 ```bash # ❌ 不加 --all-keys 会报错 ./redis-delete --mode cluster --host 10.10.2.12 --port 7001 --key-prefix "*" --export # Error: wildcard pattern requires --all-keys flag # ✅ 必须加上 --all-keys 确认 ./redis-delete \ --mode cluster \ --host 10.10.2.12 \ --port 7001 \ --key-prefix "*" \ --all-keys \ --export ``` ### 5. 错误日志 删除操作会生成详细的错误日志文件 `delete.err`,记录所有失败的 key 和错误原因。 **错误日志格式**: ``` [2026-01-20 15:30:45] [PARTIAL_FAILURE] 98 deleted, 2 failed - cache:user:1001 - cache:user:1002 [2026-01-20 15:31:20] [BATCH_ERROR] connection refused - cache:session:abc - cache:session:def ``` **错误类型**: - `PARTIAL_FAILURE`:批次中部分 key 删除失败(已记录具体 key) - `BATCH_ERROR`:整个批次失败(网络错误、Redis 错误等) - `FATAL_ERROR`:致命错误(连接断开、权限错误等),程序会立即停止 **实时进度显示**: ```bash # 删除操作会显示实时进度(每批次更新同一行) Progress: 10000 scanned, 100 batches, 9800 deleted, 200 failed ``` **致命错误处理**: 以下错误会立即停止执行: - 连接错误(`connection refused`、`i/o timeout`、`broken pipe`) - 权限错误(`NOAUTH`、`NOPERM`) - 超时错误(`timeout`) - 上下文取消(`context canceled`) ```bash # 示例:权限错误导致立即停止 ./redis-delete --mode cluster --host 10.10.2.12 --port 7001 --del # [INFO] Starting delete mode... # [ERROR] Fatal error during deletion: NOAUTH Authentication required # 💡 提示:检查密码配置,或查看 delete.err 获取详细信息 ``` ## 核心实现 ### 流式处理架构 工具采用**流式处理架构**,避免将所有数据加载到内存: ``` ┌─────────────┐ │ Redis SCAN │ ← 持续扫描 └──────┬──────┘ │ keys ↓ ┌─────────┐ │ Channel │ ← 缓冲区 (1000) └────┬────┘ │ ↓ ┌──────────────┐ │ 流式写入文件 │ ← bufio 缓冲 └──────────────┘ ``` **优势**: - 💾 **内存占用恒定**:100 万 key 内存占用 < 10MB(导出 key),< 50MB(导出 key-value) - ⚡ **高性能**:边扫描边写入,无等待 - 🛡️ **安全**:文件写入失败立即中止,不丢失数据 - 📊 **可扩展**:支持千万级 key 处理 **导出 key-value 流式处理**: 使用滑动窗口算法实现流式处理: ``` ┌────────────┐ │ SCAN key1 │ ┐ │ SCAN key2 │ │ 滑动窗口 │ SCAN key3 │ │ (batch-size) │ ... key100 │ ┘ └─────┬──────┘ │ 满了 ↓ ┌──────────┐ │ MGET │ → 批量获取值 └─────┬────┘ │ ↓ ┌──────────┐ │ 写入文件 │ └──────────┘ │ ↓ 清空窗口 ← 继续扫描 ``` **安全保护**: - 🛡️ `--max-value-size` 限制单个 value 大小(默认 10MB),防止内存爆炸 - 🚫 超过限制的 key 会被跳过并记录到日志 ### Cluster Slot 批量删除 在 Cluster 模式下,工具自动计算 slot 并按分组批量删除,避免 CROSSSLOT 错误: 1. **扫描阶段**:导出纯 key 列表 2. **删除阶段**:使用 CRC16 算法实时计算每个 key 的 slot,按 slot 分组后批量删除 3. **错误避免**:同一批次的 key 属于同一 slot,不会触发 CROSSSLOT 错误 **优势**: - 📝 **格式统一**:所有模式导出格式一致 - 🔄 **兼容性强**:可以直接使用 standalone 模式的导出文件在 cluster 模式删除 - ⚡ **性能无损**:CRC16 计算开销极小 ## 参数说明 ### 连接参数 | 参数 | 说明 | 默认值 | 示例 | |------|------|--------|------| | `--mode` | Redis 模式 | standalone | standalone, sentinel, cluster | | `--host` | Redis 主机地址 | 127.0.0.1 | 192.168.1.100 | | `--port` | Redis 端口 | 6379 | 6379, 7001 | | `--password` | Redis 密码 | (空) | your_password | | `--db` | 数据库编号(standalone) | 0 | 3, 10 | ### Sentinel 参数 | 参数 | 说明 | 默认值 | 示例 | |------|------|--------|------| | `--sentinel-host` | Sentinel 地址 | (使用 --host) | 192.168.1.200 | | `--sentinel-port` | Sentinel 端口 | 26379 | 26379 | | `--sentinel-password` | Sentinel 密码 | (空) | sentinel_password | | `--master-name` | 主节点名称 | mymaster | mymaster, redis-master | ### Cluster 参数 | 参数 | 说明 | 默认值 | 示例 | |------|------|--------|------| | `--cluster-nodes` | 集群节点列表(逗号分隔) | (自动发现) | "192.168.1.50:7001,192.168.1.51:7002" | ### 操作参数 | 参数 | 说明 | 必需 | 示例 | |------|------|------|------| | `--export` | 导出模式 | 是(四选一) | --export | | `--del` | 删除模式 | 是(四选一) | --del | | `--direct` | 直接模式 | 是(四选一) | --direct | | `--restore` | 恢复模式 | 是(四选一) | --restore | | `--key-prefix` | 要删除的 key 前缀 | export/direct 必需 | "cache:", "temp:" | | `--export-with-values` | 导出 key-value 对(较慢但可恢复) | 可选 | --export-with-values | | `--max-value-size` | 导出时最大 value 大小(支持 k/KB/m/MB/g/GB) | 可选 | 10MB, 1GB, 0=无限制 | | `--restore-file` | 恢复文件路径(restore 必需) | restore 必需 | work/keys_to_delete.txt | ### 白名单参数 | 参数 | 说明 | 示例 | |------|------|------| | `--whitelist-keys` | 精确白名单 keys(逗号分隔,支持引号) | "key1,key2,key3" 或 '"key1,comma",key2' | | `--whitelist-prefixes` | 前缀白名单(逗号分隔,支持引号) | "config:,system:" 或 '"prefix:,comma",normal:' | ### 性能参数 | 参数 | 说明 | 默认值 | 示例 | |------|------|--------|------| | `--batch-size` | 批量大小 | 100 | 100, 500, 1000 | | `--batch-delay` | 每批之间的延迟 | 200ms | 0ms, 100ms, 1s | | `--scan-count` | SCAN 命令 COUNT 参数 | 200 | 100, 500, 1000 | ### 安全参数 | 参数 | 说明 | 默认值 | |------|------|--------| | `--dry-run` | 试运行:预览操作但不执行 | false | | `--all-keys` | 允许导出/删除所有 keys | false | | `--export-file` | 导出文件路径(基于 work-dir) | work/keys_to_delete.txt | | `--work-dir` | 工作目录(导出文件所在目录) | work | ## 故障排查 ### DB 参数错误(Standalone/Sentinel 模式) 在 Standalone 和 Sentinel 模式下,删除操作必须显式指定 `--db` 参数: ```bash # ❌ 错误:不指定 --db 参数 ./redis-delete --mode standalone --host 192.168.1.100 --port 6379 --del # Error: must explicitly specify --db parameter for delete mode # ✅ 正确:明确指定要操作的数据库 ./redis-delete --mode standalone --host 192.168.1.100 --port 6379 --db 3 --del ``` **注意**:Cluster 模式不需要 `--db` 参数(Redis Cluster 不支持多数据库)。 ### Standalone 模式连接 Cluster 的错误 如果你使用 `--mode standalone` 连接到 Redis Cluster 节点,会看到以下错误: ```bash ./redis-delete --mode standalone --host 192.168.1.50 --port 7001 --db 3 --del # Error: ERR SELECT is not allowed in cluster mode # # 💡 提示:如果你连接的是 Redis Cluster,请使用 --mode cluster 参数 ``` **解决方案**: 1. **确认后端 Redis 类型**: ```bash # 检查是否是 Cluster redis-cli -c -h 192.168.1.50 -p 7001 CLUSTER INFO ``` 2. **如果是 Redis Cluster**: ```bash # 使用 cluster 模式(不需要 --db 参数) ./redis-delete --mode cluster --host 192.168.1.50 --port 7001 --del ``` ### 连接错误 ```bash # 检查 Redis 是否可访问 redis-cli -h 192.168.1.100 -p 6379 -a "password" ping # Cluster 模式使用 -c 参数 redis-cli -c -h 192.168.1.50 -p 7001 -a "password" ping ``` ### 权限错误 确保使用的账户有以下权限: - SCAN 命令(扫描 keys) - DEL 命令(删除 keys) - Cluster 模式需要 CLUSTER NODES 命令 - Sentinel 模式需要 SENTINEL 命令 ### CROSSSLOT 错误 如果在集群模式下遇到 CROSSSLOT 错误: 1. 确保使用 `--mode cluster` 2. 不要使用 `--mode standalone` 连接集群节点 3. 工具会自动按 slot 分组批量删除 ## 性能参考 | 场景 | 数据量 | 性能 | 内存占用 | 说明 | |------|--------|------|----------|------| | 快速导出(只导出 key) | 100万 key | ~10-30秒 | < 10MB | ✅ 推荐(无 batch-delay 限制) | | 完整导出(导出 key-value) | 100万 key | ~30-60秒 | ~50MB | 恢复场景(MGET 获取值) | | 删除模式(从文件) | 100万 key | ~33分钟 | < 10MB | ⚠️ 受 batch-delay 限制(见下方说明) | | Direct 模式(扫描+删除) | 100万 key | ~33分钟 | < 10MB | ⚠️ 不可逆,受 batch-delay 限制 | *测试环境:本地 Redis,网络延迟 < 1ms,默认配置(batch-size=100, batch-delay=200ms)* **重要说明**: - **导出操作**不受 `batch-delay` 限制,主要是 SCAN 命令扫描 + 文件写入,速度很快 - **删除/恢复操作**受 `batch-delay` 限制(默认 200ms),计算公式: - 总时间 = (数据量 ÷ batch-size) × batch-delay - 100万 key = 10,000批 × 200ms = 2000秒 ≈ 33分钟 - **生产环境建议**:降低 `--batch-delay` 或增大 `--batch-size` 以提高速度 ### 推荐配置 | 场景 | 推荐模式 | 预期性能 | 配置建议 | |------|---------|---------|---------| | 大批量删除(100万+) | Export → Delete | 最快 | batch-delay=50ms, batch-size=500 | | 需要恢复能力 | Export with values | 较慢,但可恢复 | batch-delay=50ms, batch-size=500 | | 少量快速删除(< 1万) | Direct(谨慎) | 快速,但不可逆 | 默认配置即可 | ### 性能调优参数 | 参数 | 默认值 | 推荐值(大数据量) | 说明 | |------|--------|------------------|------| | `--batch-size` | 100 | 500-1000 | 增大批次可减少批次数,提高吞吐量 | | `--batch-delay` | 200ms | 50-100ms | **生产环境可降低**,减少延迟显著提高速度 | | `--scan-count` | 200 | 500-1000 | SCAN 命令 COUNT 参数,影响扫描速度 | **性能优化示例**: ```bash # 100万 key 快速删除(约 1-2 分钟) ./redis-delete --mode standalone \ --batch-size 1000 \ --batch-delay 50ms \ --del ``` **注意**: - 调整参数前请先在测试环境验证 - 降低 `--batch-delay` 会增加对 Redis 的瞬时压力 - 增大 `--batch-size` 会增加单次 DEL 命令的参数数量(Redis 单命令最大参数数受限于 Redis 服务器的 `max-argc` 配置)