Java应用通过Jedis或Redisson实现Redis map分页查询的方法咨询
Redis Hash(Map)分页拉取实现方案
Redis 本身没有为Hash结构提供原生的范围分页查询指令,针对100MB量级的Hash数据,推荐使用HSCAN增量迭代指令实现分批拉取,既不会阻塞Redis实例,也能灵活控制每次拉取的数据量,避免带宽占用过高。下面分别给出Jedis和Redisson两款客户端的实现方式:
Jedis 实现
Jedis直接封装了原生的hscan指令,你需要手动处理游标迭代逻辑:
- 核心逻辑:初始游标传入
0,每次迭代后使用返回的新游标发起下一次请求,直到游标返回0即遍历完成 - 可通过
count参数指定单次拉取的条目数量hint,Redis会尽可能返回接近该数量的条目
代码示例:
import redis.clients.jedis.Jedis; import redis.clients.jedis.ScanParams; import redis.clients.jedis.ScanResult; import java.util.Map; public class HashPageDemo { public void pageFetchHash(String hashKey) { // 替换为自身业务的Jedis实例获取逻辑 try (Jedis jedis = new Jedis("127.0.0.1", 6379)) { String cursor = ScanParams.SCAN_POINTER_START; // 可根据单条entry大小调整批次大小,比如单条1KB的话单次拉100条就是100KB左右 ScanParams scanParams = new ScanParams().count(100); do { ScanResult<Map.Entry<String, String>> scanResult = jedis.hscan(hashKey, cursor, scanParams); // 本次拉取到的批次数据,可直接返回给UI做展示 Map<String, String> batchData = scanResult.getResult(); // 处理业务逻辑 handleBatchData(batchData); // 更新游标 cursor = scanResult.getCursor(); } while (!"0".equals(cursor)); } } private void handleBatchData(Map<String, String> batchData) { // 业务处理逻辑 } }
Redisson 实现
Redisson已经对HSCAN做了高度封装,无需手动处理游标,直接调用封装好的迭代器即可:
- 调用
entryIterator方法时传入的参数即为单次拉取的批次大小 - 迭代器会自动处理游标更迭、异常重试等逻辑,代码更简洁
代码示例:
import org.redisson.Redisson; import org.redisson.api.RMap; import org.redisson.api.RedissonClient; import org.redisson.config.Config; import java.util.Map; public class RedissonHashPageDemo { public void pageFetchHash(String hashKey) { // 替换为自身业务的Redisson配置 Config config = new Config(); config.useSingleServer().setAddress("redis://127.0.0.1:6379"); RedissonClient redisson = Redisson.create(config); RMap<String, String> redisMap = redisson.getMap(hashKey); // 单次拉取100条 Iterable<Map.Entry<String, String>> entryIterator = redisMap.entryIterator(100); for (Map.Entry<String, String> entry : entryIterator) { // 处理单条数据,也可攒够批次后统一返回给UI handleEntry(entry); } } private void handleEntry(Map.Entry<String, String> entry) { // 业务处理逻辑 } }
注意事项与优化建议
- 如果业务需要支持前端跳转到指定页码的分页场景,不推荐直接使用
HSCAN,可以额外维护一个ZSet结构存储Hash的所有field,将页码作为权重,使用ZRANGE指令拿到对应页的field列表后,再调用HMGET批量获取对应value,分页精度更高 - 不要使用
HKEYS或者HGETALL先拉全量数据再内存分页,数据量较大时会占用过多Redis输出缓冲区,同时也会造成带宽浪费 - 热点分页数据可以增加本地缓存层,减少重复请求Redis的次数,进一步降低带宽消耗
内容的提问来源于stack exchange,提问作者dev Joshi
相关产品推荐
相关产品推荐

