遇到的问题:
redis中有个zset格式数据,不停的写入,写入间隔远远小于key的过期时间,导致一段时间后发现其中的一些key变的比较大,一度达到了43M。

好在这些key的score是秒级时间戳,而是有用的数据也是最近7天的。
这个是数据的存储格式:

现在需要将这个前缀的所有key中,7天之前的数据全部删除。
问题解决:
一开始使用的是 shell 脚本,但是发现删除的过程中,产生了大量的连接,导致线上报警。
后面考虑使用Java 编写脚本,使用连接池和长连接的方式来删除。
这个db中,存放的key有多种前缀的,我们只需要删除其中的一种,而且这种前缀的key数量也比较大。
如果直接使用 keys * 后再遍历,那就直接背包走人了。我们可以使用 scan 命令来删除。下面是代码:
import redis.clients.jedis.*;
import java.util.List;
public class ClearBigkeyDemo {
private static final String redisHost = "127.0.0.1";
private static final String passWd = "admin";
private static JedisPool jedisPool;
private static Jedis jedis;
private static void init() {
JedisPoolConfig config = new JedisPoolConfig();
config.setTestWhileIdle(true);
config.setMinEvictableIdleTimeMillis(60000);
config.setTimeBetweenEvictionRunsMillis(30000);
config.setNumTestsPerEvictionRun(-1);
config.setMaxIdle(60);
jedisPool = new JedisPool(config, redisHost, 6379, 1000, passWd, 4);
jedis = jedisPool.getResource();
}
public static void main(String[] args) {
// 初始化redis连接池
init();
// 需要删除的数据的 前缀
String matchKey = "USR:INFO:UID_*";
// scan 的首个游标采用默认的 0
String cursor = ScanParams.SCAN_POINTER_START;
// 创建配置
ScanParams scanParams = new ScanParams();
// 每次10个游标
scanParams.count(10);
// 模糊匹配的key
scanParams.match(matchKey);
// 需要删除多久之前的数据,endTime 是时间戳
long endTime = 1621867991000L;
// 是否还没有遍历完
boolean isNull = true;
// 开始遍历
while (isNull) {
// 获取 scan
ScanResult<String> scanResult = jedis.scan(cursor, scanParams);
// 下个游标值
String nextCursor = scanResult.getStringCursor();
// 为了清楚点,把下次遍历的游标替换
cursor = nextCursor;
// 获取到的key,是一个 list
List<String> result = scanResult.getResult();
// 遍历这个 list
for (String zkey: result) {
jedis.zremrangeByScore(zkey,0,endTime);
}
// 当遍历完时,此时游标值又会变为0
if ("0".equals(nextCursor)) {
// 将循环条件置否,用于跳出循环
isNull = false;
}
}
// 关闭连接,一定要关闭
jedis.close();
jedisPool.close();
}
}
需要的依赖只有一个,按照自己的redis的版本来配置
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
完毕。
针对Redis中ZSet数据过大问题,本文提出了一种解决方案。通过Java编写脚本,利用Jedis连接池和Scan命令,避免了大量的连接报警。代码示例展示了如何删除7天前的特定前缀key,从而优化存储空间。这种方法避免了`keys`命令可能导致的性能问题。
443

被折叠的 条评论
为什么被折叠?



