You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何减少Redisson嵌套RMap的Redis服务器调用次数?

嘿,这个嵌套RMap多次远程调用的问题我之前踩过坑!确实,每次get()都走网络请求,四层下来耗时肯定感人,给你几个开源版Redisson能用的优化方案,都能把调用次数降到1次:

方案1:把嵌套结构封装成单个Java对象存储

最直接的思路是把你的四层嵌套Map结构,封装成一个自定义的POJO类,让Redisson把这个对象作为整体序列化后存在RMap的value里。这样你只需要一次get()拿到整个对象,后续的嵌套取值全在本地内存里完成,完全不会再触发Redis请求。

举个代码例子:

// 先定义封装嵌套结构的POJO,Redisson默认用Jackson序列化,字段要有getter/setter即可
class NestedCacheData {
    private Map<String, List<String>> level2Map;

    public Map<String, List<String>> getLevel2Map() {
        return level2Map;
    }

    public void setLevel2Map(Map<String, List<String>> level2Map) {
        this.level2Map = level2Map;
    }
}

// 使用时的代码
RMap<String, NestedCacheData> map = redisClient.getMap("mycache");
String result = Optional.ofNullable(map.get(key1))
                        .map(NestedCacheData::getLevel2Map)
                        .map(level2 -> level2.get(key2))
                        // 这里可以继续处理后续的嵌套层级,全是本地操作
                        .orElse(null);

这样只有map.get(key1)这一次Redis远程调用,后面的所有取值都在本地完成,性能提升非常明显。

方案2:用RBucket存储整个大结构(适合单key缓存场景)

如果你的整个缓存其实就是一个单一的嵌套结构,不需要用RMap的多key特性,那直接用RBucket更简单——它专门用来存储单个对象,一次get()就能把整个嵌套结构拉到本地:

RBucket<Map<String, Map<String, List<String>>>> cacheBucket = redisClient.getBucket("mycache");
String result = Optional.ofNullable(cacheBucket.get())
                        .map(topMap -> topMap.get(key1))
                        .map(level2Map -> level2Map.get(key2))
                        .orElse(null);

这个方案同样只有一次Redis调用,代码更简洁,适合缓存内容是单一整体的场景。

方案3:批量获取多个顶层key(如果需要取多个值)

要是你需要一次性获取多个顶层key对应的嵌套值,可以用RMapgetAll(Collection<?> keys)方法,一次请求就能拿到所有顶层value,之后的嵌套取值全在本地处理。比如原来取4个key需要4次调用,现在只需要1次:

List<String> targetKeys = Arrays.asList(key1, key2, key3);
Map<String, NestedCacheData> allData = map.getAll(targetKeys);
// 遍历allData处理每个key的嵌套取值,全程本地操作

为什么原来的方式会多次调用?

顺便解释下原因:Redisson返回的RMap其实是一个代理对象,它的get()方法并不是直接操作本地内存,而是会触发远程Redis请求——因为Redisson要保证你拿到的是最新的缓存数据。所以你嵌套调用get(),就会触发多次远程请求,四层就是四次网络往返,耗时自然高。

最后提个小建议:如果追求序列化性能,可以给Redisson配置Kryo序列化替代默认的Jackson,序列化/反序列化速度会更快,进一步降低整体耗时。

内容的提问来源于stack exchange,提问作者Pravat Kumar Sahoo

火山引擎 最新活动