Spring RedisTemplate实现scan操作
老生常谈,keys不安全,因为
- keys的操作会导致数据库暂时被锁住,其他的请求都会被堵塞;业务量大的时候会出问题
Spring RedisTemplate实现scan
1. hscan sscan zscan
- 例子中的"field"是值redis的key,即从key为"field"中的hash中查找
- redisTemplate的opsForHash,opsForSet,opsForZSet 可以 分别对应 sscan、hscan、zscan
- 也可以使用
(JedisCommands) connection.getNativeConnection()
的 hscan、sscan、zscan 方法实现cursor遍历,参照下文2.2章节
try { Cursor<Map.Entry<Object,Object>> cursor = redisTemplate.opsForHash().scan("field", ScanOptions.scanOptions().match("*").count(1000).build()); while (cursor.hasNext()) { Map.Entry<Object,Object> entry = cursor.next(); Object key = entry.getKey(); Object valueSet = entry.getValue(); } //关闭cursor cursor.close(); } catch (IOException e) { e.printStackTrace(); }
- cursor.close(); 游标一定要关闭,不然连接会一直增长;可以使用
client lists
info clients
info stats
命令查看客户端连接状态,会发现scan操作一直存在 - 我们平时使用的redisTemplate.execute 是会主动释放连接的,可以查看源码确认
- 代码虽然只是调用一次scan方法,但是spring-data-redis已经对scan做了封装,这个scan结合cursor.hasNext会多次redis scan,最终拿到所有match的结果
2. scan
2.1 使用spring-data-redis封装好的scan方法
public Set<String> scan(String matchKey) { Set<String> keys = redisTemplate.execute((RedisCallback<Set<String>>) connection -> { Set<String> keysTmp = new HashSet<>(); Cursor<byte[]> cursor = connection.scan(new ScanOptions.ScanOptionsBuilder()
.match("*" + matchKey + "*").count(1000).build()); while (cursor.hasNext()) { keysTmp.add(new String(cursor.next())); } return keysTmp; }); return keys; }
项目中我用的就是这种方法来代替
Set keys = redisTemplate.keys(uploadTag + entity.getCaseNo() + ":*");
分类:
工作日常记录
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧