15 redis如何做分页查询
1.使用redis的list(列表)数据结构
将需要分页展示的数据的id或者主键作为list中的元素,然后根据用户的分页请求,
使用LRANGE命令来获取指定范围的元素,再根据元素来获取具体的数据
1 2 3 4 5 6 7 8 9 10 11
| @Service public class RedisPaginationService { @Autowired private RedisTemplate<String, String> redisTemplate;
public List<String> getPaginatedData(String key, int pageNumber, int pageSize) { long start = (pageNumber - 1) * pageSize; long end = start + pageSize - 1; return redisTemplate.opsForList().range(key, start, end); } }
|
2.使用redis的ZSet(有序集合)数据结构
将需要分页展示的数据的id或者主键作为ZSet中的value,将数据的排序依据(比如时间、热度、评分等)作为ZSet中的score,然后根据用户的分页请求,
使用ZRANGE或者ZREVRANGE命令来获取指定范围的value,再根据value来获取具体的数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| public PageResult<Article> getArticlesByPage(Long userId, Long lastScore, Integer offset, int pageSize) { String cacheKey = "user:articles:" + userId; ZSetOperations<String, String> zSetOps = redisTemplate.opsForZSet();
Set<ZSetOperations.TypedTuple<String>> tuples = zSetOps.reverseRangeByScoreWithScores( cacheKey, 0, lastScore, offset, pageSize );
if (tuples == null || tuples.isEmpty()) { return reloadFromDatabase(userId, pageSize); }
List<Article> articles = new ArrayList<>(); long minScore = 0; int newOffset = 1; for (ZSetOperations.TypedTuple<String> tuple : tuples) { Article article = deserialize(tuple.getValue()); articles.add(article); long score = tuple.getScore().longValue(); if (score == minScore) { newOffset++; } else { minScore = score; newOffset = 1; } }
return new PageResult<>(articles, minScore, newOffset); }
|
3.使用redis的hash(哈希)数据结构
将需要分页展示的数据的id或者主键作为hash中的field,将数据的排序依据(比如时间、热度、评分等)作为hash中的value,然后根据用户的分页请求,
使用HSCAN命令来获取指定范围的field和value,再根据field来获取具体的数据。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| @Autowired private RedisTemplate<String, Object> redisTemplate;
public void addData(String hashKey, String itemId, Object data, double score) { redisTemplate.opsForHash().put(hashKey, itemId, data); redisTemplate.opsForZSet().add(hashKey + ":index", itemId, score); }
public List<Object> getPage(String hashKey, int page, int pageSize) { String zsetKey = hashKey + ":index"; long start = (page - 1) * (long) pageSize; long end = start + pageSize - 1;
Set<String> itemIds = redisTemplate.opsForZSet().range(zsetKey, start, end); if (itemIds == null) return Collections.emptyList();
return redisTemplate.opsForHash().multiGet(hashKey, itemIds); }
|
4.扩展ZREVRANGE
ZREVRANGE命令用于返回有序集合中,指定区间内的成员,其中成员的位置按分数值递减(从大到小)来排列。具有相同分数值的成员按字典序的逆序(reverse lexicographical order)排列。
ZREVRANGE命令的基本语法如下:
1
| redis> ZREVRANGE key start stop [WITHSCORES]
|
具体可以参考博客:
如何使用redis实现高效的分页功能