news 2026/6/10 17:47:16

清理三主三从redis集群的过期key和键值超过10M的key

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
清理三主三从redis集群的过期key和键值超过10M的key

一.基于shell脚本进行删除

针对 Redis 三主三从集群,要实现定时清理过期 Key + 超过 10M 的超大 Key,核心思路是:

  1. 自动识别集群所有主节点(从节点无需清理,数据同步主节点);
  2. 基于SCAN非阻塞遍历主节点 Key,筛选目标后删除;
  3. 通过 Linuxcrontab配置定时任务,低峰期自动执行。

以下是基于shell脚本实现

#!/bin/bash # Redis 集群清理脚本:删除过期 Key + 超过10M的Key # 适配三主三从集群,仅清理主节点 ########################## 配置区(根据实际修改) ########################## # Redis 集群任意节点地址(用于获取主节点列表) CLUSTER_ANY_NODE="10.10.19.11:6379" # Redis 密码(无密码则注释此行,后续删除 -a $REDIS_PASSWORD) REDIS_PASSWORD="your_redis_password" # 超大 Key 阈值:10M(字节) MAX_KEY_SIZE=$((10 * 1024 * 1024)) # SCAN 每次遍历 Key 数量(建议 100-500,越小越不阻塞) SCAN_COUNT=500 # 日志文件路径 LOG_FILE="/var/log/redis_cluster_clean.log" ########################################################################### # 日志函数(带时间戳) log() { echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" >> $LOG_FILE } # 检查 redis-cli 是否存在 if ! command -v redis-cli &> /dev/null; then log "错误:未找到 redis-cli,请确保 Redis 客户端已安装" exit 1 fi # 步骤1:获取集群所有主节点(过滤从节点、空行) log "开始获取集群主节点列表..." MASTER_NODES=$(redis-cli -h $(echo $CLUSTER_ANY_NODE | cut -d':' -f1) \ -p $(echo $CLUSTER_ANY_NODE | cut -d':' -f2) \ -a $REDIS_PASSWORD --raw CLUSTER NODES 2>> $LOG_FILE \ | grep -E "master|myself,master" \ | awk '{print $2}' \ | cut -d'@' -f1 \ | sort -u) if [ -z "$MASTER_NODES" ]; then log "错误:未获取到集群主节点,请检查集群连接或密码" exit 1 fi log "获取到主节点列表:$MASTER_NODES" # 步骤2:遍历每个主节点,清理目标 Key TOTAL_DELETED_EXPIRED=0 # 累计删除过期 Key 数 TOTAL_DELETED_LARGE=0 # 累计删除超大 Key 数 for NODE in $MASTER_NODES; do NODE_HOST=$(echo $NODE | cut -d':' -f1) NODE_PORT=$(echo $NODE | cut -d':' -f2) log "开始清理主节点:$NODE_HOST:$NODE_PORT" # 初始化 SCAN 游标 CURSOR=0 # 节点内删除计数 NODE_EXPIRED=0 NODE_LARGE=0 # 循环 SCAN 遍历当前节点所有 Key while :; do # 执行 SCAN 命令(--raw 避免中文/特殊字符乱码) SCAN_RESULT=$(redis-cli -h $NODE_HOST -p $NODE_PORT -a $REDIS_PASSWORD \ --raw SCAN $CURSOR COUNT $SCAN_COUNT 2>> $LOG_FILE) # 解析游标(第一行)和 Key 列表(剩余行) NEW_CURSOR=$(echo "$SCAN_RESULT" | head -n 1) KEYS=$(echo "$SCAN_RESULT" | tail -n +2) # 遍历当前批次 Key for KEY in $KEYS; do # 跳过空 Key [ -z "$KEY" ] && continue # 条件1:删除已过期 Key(TTL ≤ 0,-2=Key不存在,-1=永不过期,0=已过期) TTL=$(redis-cli -h $NODE_HOST -p $NODE_PORT -a $REDIS_PASSWORD --raw TTL "$KEY" 2>> $LOG_FILE) if [ "$TTL" -le 0 ] && [ "$TTL" -ne -1 ]; then # 排除永不过期的 Key redis-cli -h $NODE_HOST -p $NODE_PORT -a $REDIS_PASSWORD DEL "$KEY" >> /dev/null 2>&1 NODE_EXPIRED=$((NODE_EXPIRED + 1)) log "[$NODE] 删除过期 Key: $KEY (TTL: $TTL)" continue fi # 条件2:删除超过10M的 Key KEY_SIZE=$(redis-cli -h $NODE_HOST -p $NODE_PORT -a $REDIS_PASSWORD --raw MEMORY USAGE "$KEY" 2>> $LOG_FILE) # 防止 MEMORY USAGE 返回非数字(如 Key 被并发删除) if [[ "$KEY_SIZE" =~ ^[0-9]+$ ]] && [ "$KEY_SIZE" -gt "$MAX_KEY_SIZE" ]; then redis-cli -h $NODE_HOST -p $NODE_PORT -a $REDIS_PASSWORD DEL "$KEY" >> /dev/null 2>&1 NODE_LARGE=$((NODE_LARGE + 1)) log "[$NODE] 删除超大 Key: $KEY (大小: $KEY_SIZE 字节,阈值: $MAX_KEY_SIZE 字节)" fi done # 游标为 0 表示当前节点遍历完成 if [ "$NEW_CURSOR" = "0" ]; then break fi CURSOR=$NEW_CURSOR done # 累计节点删除数 TOTAL_DELETED_EXPIRED=$((TOTAL_DELETED_EXPIRED + NODE_EXPIRED)) TOTAL_DELETED_LARGE=$((TOTAL_DELETED_LARGE + NODE_LARGE)) log "[$NODE] 清理完成:过期 Key 删 $NODE_EXPIRED 个,超大 Key 删 $NODE_LARGE 个" done # 步骤3:输出总清理结果 log "==================== 清理汇总 ====================" log "集群总清理:过期 Key 共 $TOTAL_DELETED_EXPIRED 个,超大 Key 共 $TOTAL_DELETED_LARGE 个" log "===================================================" log " " # 空行分隔日志 exit 0

二.基于lua脚本删除

在 Redis 三主三从集群中使用 Lua 脚本清理过期 Key超过 10M 的超大 Key,核心优势是:

  1. Lua 脚本在 Redis 服务端原子执行,减少网络往返(相比 Shell/Python 遍历更高效);
  2. 结合SCAN非阻塞遍历,避免阻塞主线程;
  3. 适配集群特性(仅清理主节点,从节点同步删除结果)。

创建redis_clean.lua,实现单节点的 Key 筛选与删除(可直接在 Redis 节点执行)

-- Redis 单节点清理脚本:删除过期 Key + 超过10M的超大 Key -- 参数说明: -- ARGV[1] = 超大 Key 阈值(字节,如 10485760 表示 10M) -- ARGV[2] = SCAN 每次遍历数量(如 200) -- 初始化变量 local max_key_size = tonumber(ARGV[1]) local scan_count = tonumber(ARGV[2]) local cursor = "0" local deleted_expired = 0 -- 过期 Key 删除计数 local deleted_large = 0 -- 超大 Key 删除计数 local batch_del = {} -- 批量删除缓存(避免频繁 DEL) local batch_max = 50 -- 每批次最多删 50 个 Key -- 循环 SCAN 遍历所有 Key repeat -- 执行 SCAN:cursor = 下一个游标, keys = 当前批次 Key 列表 local scan_result = redis.call("SCAN", cursor, "COUNT", scan_count) cursor = scan_result[1] local keys = scan_result[2] -- 遍历当前批次 Key for _, key in ipairs(keys) do -- 跳过空 Key if key == nil or key == "" then goto continue end -- 条件1:删除已过期 Key(ttl ≤ 0 且 不是永不过期) local ttl = redis.call("TTL", key) if ttl <= 0 and ttl ~= -1 then table.insert(batch_del, key) deleted_expired = deleted_expired + 1 goto continue -- 满足过期条件,无需检查大小 end -- 条件2:删除超过阈值的超大 Key local size = redis.call("MEMORY", "USAGE", key) if tonumber(size) > max_key_size then table.insert(batch_del, key) deleted_large = deleted_large + 1 end ::continue:: -- 批量删除:达到批次上限则执行 DEL if #batch_del >= batch_max then redis.call("DEL", unpack(batch_del)) batch_del = {} -- 清空缓存 end end -- 游标为 0 时结束遍历 until cursor == "0" -- 处理剩余未删除的 Key if #batch_del > 0 then redis.call("DEL", unpack(batch_del)) end -- 返回清理结果 return { ["deleted_expired"] = deleted_expired, ["deleted_large"] = deleted_large }

编写redis_cluster_lua_clean.sh,自动识别集群主节点,逐个执行 Lua 脚本(适配三主三从集群):

#!/bin/bash # Redis 三主三从集群清理脚本(Lua 版) # 自动识别主节点 → 执行 Lua 脚本 → 输出清理结果 ########################## 配置区(根据实际修改) ########################## # Redis 集群任意节点(用于获取主节点列表) CLUSTER_NODE="192.168.1.10:6379" # Redis 密码(无密码则删除 -a $REDIS_PWD) REDIS_PWD="your_redis_password" # 超大 Key 阈值:10M(字节) MAX_SIZE=$((10 * 1024 * 1024)) # SCAN 每次遍历数量(建议 200-500) SCAN_COUNT=200 # Lua 脚本路径 LUA_SCRIPT="/path/to/redis_clean.lua" # 日志文件 LOG_FILE="/var/log/redis_cluster_lua_clean.log" ########################################################################### # 日志函数(带时间戳) log() { echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" >> $LOG_FILE } # 检查依赖 if ! command -v redis-cli &> /dev/null; then log "错误:未找到 redis-cli,请安装 Redis 客户端" exit 1 fi if [ ! -f "$LUA_SCRIPT" ]; then log "错误:Lua 脚本不存在 → $LUA_SCRIPT" exit 1 fi # 步骤1:获取集群所有主节点 log "开始获取集群主节点列表..." MASTER_NODES=$(redis-cli -h $(echo $CLUSTER_NODE | cut -d':' -f1) \ -p $(echo $CLUSTER_NODE | cut -d':' -f2) \ -a $REDIS_PWD --raw CLUSTER NODES 2>> $LOG_FILE \ | grep -E "master|myself,master" \ | awk '{print $2}' | cut -d'@' -f1 | sort -u) if [ -z "$MASTER_NODES" ]; then log "错误:未获取到主节点,请检查集群连接/密码" exit 1 fi log "获取到主节点:$MASTER_NODES" # 步骤2:遍历主节点执行 Lua 脚本 TOTAL_EXPIRED=0 TOTAL_LARGE=0 for NODE in $MASTER_NODES; do HOST=$(echo $NODE | cut -d':' -f1) PORT=$(echo $NODE | cut -d':' -f2) log "开始清理主节点 → $HOST:$PORT" # 执行 Lua 脚本(--eval 加载脚本,ARGV 传参) RESULT=$(redis-cli -h $HOST -p $PORT -a $REDIS_PWD --raw \ EVAL "$(cat $LUA_SCRIPT)" 0 $MAX_SIZE $SCAN_COUNT 2>> $LOG_FILE) # 解析 Lua 返回结果(示例:{deleted_expired=10,deleted_large=2}) NODE_EXPIRED=$(echo $RESULT | grep -oP 'deleted_expired"\s*:\s*\K\d+') NODE_LARGE=$(echo $RESULT | grep -oP 'deleted_large"\s*:\s*\K\d+') # 兼容空结果 NODE_EXPIRED=${NODE_EXPIRED:-0} NODE_LARGE=${NODE_LARGE:-0} # 累计计数 TOTAL_EXPIRED=$((TOTAL_EXPIRED + NODE_EXPIRED)) TOTAL_LARGE=$((TOTAL_LARGE + NODE_LARGE)) log "[$HOST:$PORT] 清理完成 → 过期 Key:$NODE_EXPIRED 个,超大 Key:$NODE_LARGE 个" done # 步骤3:输出汇总 log "==================== 集群清理汇总 ====================" log "总删除:过期 Key = $TOTAL_EXPIRED 个,超大 Key = $TOTAL_LARGE 个" log "======================================================" log " " # 空行分隔日志 exit 0
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 15:45:46

JoltPhysics碰撞精度优化策略:从边缘穿透到稳定交互的实战指南

你的球体是否总在墙角"卡住"或在斜坡上"滑行"&#xff1f;物理引擎中的边缘碰撞问题如同现实世界中的"视觉盲区"&#xff0c;在曲率突变处产生非预期的物理行为。本文将为你揭示JoltPhysics在处理复杂几何边缘时的技术瓶颈&#xff0c;并提供一套…

作者头像 李华
网站建设 2026/6/10 16:48:40

WebAssembly加速PySyft:高性能隐私计算实战指南

WebAssembly加速PySyft&#xff1a;高性能隐私计算实战指南 【免费下载链接】PySyft Perform data science on data that remains in someone elses server 项目地址: https://gitcode.com/gh_mirrors/py/PySyft 在数据隐私日益重要的今天&#xff0c;如何在保护数据安全…

作者头像 李华
网站建设 2026/6/10 1:42:37

6、上网本网络连接与配件购物指南

上网本网络连接与配件购物指南 1. 网络连接相关知识 在当今数字化时代,上网本连接网络是日常使用的基础。网络连接方式多样,包括蓝牙、手机连接以及无线和有线网络连接等。 1.1 无线网络加密与连接准备 无线网络加密方式有多种,其中 WEP 是较旧的加密方式,容易被破解,…

作者头像 李华
网站建设 2026/6/10 15:41:56

Lottie-ios响应式动画控制:从状态同步难题到高效解决方案

Lottie-ios响应式动画控制&#xff1a;从状态同步难题到高效解决方案 【免费下载链接】lottie-ios airbnb/lottie-ios: Lottie-ios 是一个用于 iOS 平台的动画库&#xff0c;可以将 Adobe After Effects 动画导出成 iOS 应用程序&#xff0c;具有高性能&#xff0c;易用性和扩展…

作者头像 李华
网站建设 2026/6/10 16:50:23

24、互联世界中的隐私与安全维护

互联世界中的隐私与安全维护 在当今这个高度互联的世界里,网络安全和隐私保护至关重要。以下将为你介绍一系列实用的安全防护方法。 基础安全防护措施 安装安全软件 :安装杀毒软件、防火墙和电子邮件过滤器,并设置它们每晚自动更新,以确保防护的时效性。因为在2008年,…

作者头像 李华
网站建设 2026/6/10 16:51:17

deck.gl与Mapbox 3D图层融合:终极无遮挡实战指南

deck.gl与Mapbox 3D图层融合&#xff1a;终极无遮挡实战指南 【免费下载链接】deck.gl WebGL2 powered visualization framework 项目地址: https://gitcode.com/GitHub_Trending/de/deck.gl 你是否在使用deck.gl与Mapbox构建3D可视化应用时&#xff0c;发现图层相互穿透…

作者头像 李华