发现维护的项目中有个用户登录时间的缓存没有设置过期时间,导致产线环境的 Redis 中存在大量永不过期的废弃 Key 。
KEYS
命令虽然可以批量查询匹配的缓存 Key ,但是数据量大时会非常慢,而且很容易造成服务器卡顿,进而影响其它正常的请求。所以产线环境中一般会禁用这个命令,以防止开发人员误操作。
这里可以采用 SCAN
命令来实现类似的效果。关于 SCAN
命令的详细说明可以参考官方文档
。
命令格式如下:
SCAN cursor [MATCH pattern] [COUNT count] [TYPE type]
复制代码
命令示例:
SCAN 0 MATCH user_login_time_* COUNT 100
复制代码
该命令会返回两个值:
- 下一次扫描使用的 cursor 。
- 需要注意的是这个 cursor 每次调用并不一定比上次的值大,这个值仅对 Redis 来说有意义;
- 另外这个值返回 0 表示扫描结束了;
- 匹配到的 Key 列表。
- 并不一定每次扫描都会有匹配到的 Key 值,所以不能用返回的列表是否为空来判断扫描是否结束了;
- 有可能返回重复的 Key ;
Spring 中的 RedisTemplate
并没有直接提供 SCAN
命令的封装,但还是可以在 RedisConnection
中执行这个命令。
scan()
方法接收一个 ScanOptions
参数,可以指定每次扫描的 Key 数量( count )和匹配的字符( pattern ),返回一个 Cursor<byte[]>
类型的游标。
/**
* Use a {@link Cursor} to iterate over keys.
*
* @param options must not be {@literal null}.
* @return never {@literal null}.
* @since 1.4
* @see <a href="https://redis.io/commands/scan">Redis Documentation: SCAN</a>
*/
Cursor<byte[]> scan(ScanOptions options);
复制代码
从 RedisTemplate
中获取 RedisConnection
并调用 scan()
方法:
RedisConnection connection = stringRedisTemplate.getRequiredConnection