【问题标题】:Retrieve data from redis cache with pagination使用分页从 redis 缓存中检索数据
【发布时间】:2020-09-28 18:45:54
【问题描述】:

我有如下结构的redis缓存

private HashOperations<String, Long, Object> hashOperations;
//put data in cache
hashOperations.put("Key", 1, SomeObject);

我需要通过分页从缓存中获取数据(第一页 50 个结果,第二页接下来 50 个结果,依此类推)。这如何用spring data redis实现。任何帮助表示赞赏。

【问题讨论】:

标签: java caching redis spring-data-redis


【解决方案1】:

如果您需要保证元素的顺序,我认为您将需要某种排序集(HSCAN 是读取整个哈希的好方法,但它不能保证返回的内容的顺序并且确实如此不保证返回的数据中不会有重复数据)。唯一符合排序集描述的 Redis 数据类型是:ZSETZSETs 有类似于HASHes 的字段,但是,在它们的字段中,它们不是一个字符串值,而是一个用于对字段进行排序的double“score”。

因此,要获得“哈希分页”,您可以做的一件事是拥有一个与您的 HASH 具有所有相同字段的 ZSETHASH 将包含您字段中的数据,ZSET 将跟踪它们的顺序。

ZSETs 有一个名为ZRANGE (documentation) 的方法,它允许您从集合中获取特定数量的元素。对于 50 的“页面”大小,它看起来像这样:

# this gets you the "page" with the first 50 elements
ZRANGE 0 50

# this gets you the "page" with the second 50 elements
ZRANGE 50 100

# etc.

因此,要向 zset/hash 添加一些数据然后获取页面,您可以执行以下操作(伪代码 - 可能无法编译):

RedisTemplate<String, String> redisTemplate;

String myKey = "exampleKey";

// example of adding one record to the HASH + ZSET
String myField = "field1";
String myData = "123ABC";

// in this example data inserted into the ZSET is ordered based on when it was inserted.
// if you want to order it differently you can figure out your own way of coming up with scores
redisTemplate.opsForZSet().add(myKey + "zset", myField, System.getCurrentTimeMillis());
redisTemplate.opsForHash.put(mykey + "hash", myField, myData);

// Get one page from the hash
Set<String> first50hashFields = redisTemplate.opsForZSet().range(myKey + "zset", 0, 50);

List<String> firstPage = LinkedList<>();
for (String hashFieldKey : first50hashFields) {
     String hashFieldValue = redisTemplate.opsForHash().get(myKey + "hash", hashFieldKey);

     firstPage.add(hashFieldValue);
}

希望全字符串示例足以说明如何做到这一点。

【讨论】:

    【解决方案2】:

    我在网上找到了一些解决方法并使用了相同的方法。

    @Override
        public List<Entity> findAll(final int pageNum, final int pageSize) {
            // Please validate the pageNum and pageSize in Controller that should be positive numbers
            int tmpIndex = 0;
            int tmpEndIndex = 0;
            final List<Entity> entities = new ArrayList<>();
            try (Cursor<Entry<Object, Object>> cursor = redisTemplate.opsForHash().scan(CACHE_KEY,
                    ScanOptions.scanOptions().match("*").build())) {
                while (cursor.hasNext()) {
                    if (tmpIndex >= pageNum && tmpEndIndex < pageSize) {
                        final Entry<Object, Object> entry = cursor.next();
                        final Entity entity = (Entity) entry.getValue();
                        entities.add(entity);
                        tmpIndex++;
                        tmpEndIndex++;
                        continue;
                    }
                    if (tmpEndIndex >= pageSize) {
                        break;
                    }
                    tmpIndex++;
                    cursor.next();
                }
            } catch (Exception ex) {
                if (LOGGER.isInfoEnabled()) {
                    LOGGER.info("Exception while fetching data from redis cache : " + ex);
                }
            }
            return entities;
        }
    

    【讨论】:

      猜你喜欢
      • 2020-06-08
      • 2020-07-16
      • 2021-04-03
      • 2021-08-16
      • 2020-06-23
      • 2013-10-28
      • 2018-08-11
      • 1970-01-01
      • 2011-10-26
      相关资源
      最近更新 更多