Redis循環慢接口優化

原慢接口

List<String> keys = new ArrayList<>(Arrays.asList("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"));

List<String> res = new ArrayList<>();
for (String key : keys) {
    String value = (String) redisTemplate.opsForValue().get(key);
    if (value == null) {
        value = dataMapper.getValueFromDB(key);
        redisTemplate.opsForValue().set(key, value, 60 * 60, TimeUnit.SECONDS);
        res.add(value);
    }
}
return res;

原因分析

  1. 當keys 數據過大,RTT時間會變大。

    多個Redis命令之間會有往返時間消耗。

    使用MGET、Pipelined可以減少RTT時間

  2. 首次進入此代碼域,由於緩存爲空,全部走數據庫,也會導致接口變慢。

解決方式

Pipelined

注意:Redis集羣部署時,不同的key可能對應不同實例節點,不能被處理。

List<String> keys = new ArrayList<>(Arrays.asList("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"));

List<String> res = new ArrayList<>();
List list = redisTemplate.executePipelined((RedisCallback<Object>) connection -> {
    for (String key : keys) {
        connection.get(key.getBytes());
    }
    return null;
});
// 緩存不存在的keys
List<String> nullKeys = new ArrayList<>();
for (int i = 0; i < keys.size(); i++) {
    if (list.get(i) == null) {
        nullKeys.add(keys.get(i));
    } else {
        res.add((String) list.get(i));
    }
}
// 緩存中不存在的值調用 數據庫批量查詢
Map<String, String> values = dataMapper.getBatchValue(nullKeys);
// 添加返回值,並更新緩存
values.forEach((key, value) -> {
    redisTemplate.opsForValue().set(key, value, 60 * 60, TimeUnit.SECONDS);
    res.add(value);
});
return res;

MGET

List<String> keys = new ArrayList<>(Arrays.asList("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"));

List<String> res = new ArrayList<>();
List list = redisTemplate.opsForValue().multiGet(keys);
// 緩存不存在的keys
List<String> nullKeys = new ArrayList<>();
for (int i = 0; i < keys.size(); i++) {
    if (list.get(i) == null) {
        nullKeys.add(keys.get(i));
    } else {
        res.add((String) list.get(i));
    }
}
// 緩存中不存在的值調用 數據庫批量查詢
Map<String, String> values = dataMapper.getBatchValue(nullKeys);
// 添加返回值,並更新緩存
values.forEach((key, value) -> {
    redisTemplate.opsForValue().set(key, value, 60 * 60, TimeUnit.SECONDS);
    res.add(value);
});
return res;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章