使用 Redisson 缓存 map,但是在取出缓存后,遍历缓存的时候非常慢。
缓存部分代码
// list 是查询的数据列表
RMap<String, String> cacheNameMap = RedissonComponent.getClient()
.getMap(RedisConstant.TEST_NAME_MAP);
Map<String, String> nameMap = list.stream()
.collect(Collectors.toMap(Test::getAccountId, Test::getUserName));
cacheNameMap.putAllAsync(nameMap);
使用缓存部分代码
long start = System.currentTimeMillis();
// 查询数据
List<Test> list = this.lambdaQuery()
.eq(Test::getDeleted, CommConstant.FALSE)
.list();
log.info("查询数据耗时:{},size={}", (System.currentTimeMillis() - start), list.size());
// 获取缓存
start = System.currentTimeMillis();
RMap<String, String> cacheNameMap = RedissonComponent.getClient().getMap(RedisConstant.TEST_NAME_MAP);
log.info("获取缓存耗时:{},size={}", (System.currentTimeMillis() - start), cacheNameMap.size());
// 处理数据
start = System.currentTimeMillis();
List<TestVO> list1 = BeanCopier.mapAsList(list, TestVO.class);
list1.stream().forEach(f -> {
String name = cacheNameMap.get(f.getAccountId());
f.setUserName(StringUtils.isEmpty(name) ? null : name);
});
log.info("处理耗时:{}", (System.currentTimeMillis() - start));
// 执行结果
查询数据耗时:6955,size=200000
获取缓存耗时:0,size=200000
处理耗时:59534
使用这种方式缓存和使用缓存,在处理那部分代码中,数据量大的时候 get 就会变得很慢,我测试的是 20 万数据,其他地方都很快,就是在处理中分 get 那里耗时很长,有几分钟的耗时。
如果我把缓存中取出来的 cacheNameMap
重新放到一个 HashMap 中,处理的那部分代码耗时基本就在1秒以内,如下:
long start = System.currentTimeMillis();
// 查询数据
List<Test> list = this.lambdaQuery()
.eq(Test::getDeleted, CommConstant.FALSE)
.list();
log.info("查询数据耗时:{},size={}", (System.currentTimeMillis() - start), list.size());
// 获取缓存
start = System.currentTimeMillis();
RMap<String, String> cacheNameMap = RedissonComponent.getClient().getMap(RedisConstant.TEST_NAME_MAP);
log.info("获取缓存耗时:{},size={}", (System.currentTimeMillis() - start), cacheNameMap.size());
// 转换 HaspMap
start = System.currentTimeMillis();
Map<String, String> nameMap = new HashMap<>(cacheNameMap.size());
nameMap.putAll(cacheNameMap);
log.info("转换耗时:{}", (System.currentTimeMillis() - start));
// 处理数据
start = System.currentTimeMillis();
List<TestVO> list2 = BeanCopier.mapAsList(list, TestVO.class);
list2.stream().forEach(f -> {
String name = nameMap.get(f.getAccountId());
f.setUserName(StringUtils.isEmpty(name) ? null : name);
});
log.info("处理耗时:{}", (System.currentTimeMillis() - start));
// 执行结果
查询数据耗时:6955,size=200000
获取缓存耗时:0,size=200000
转换耗时:11072
处理耗时:379
这种处理方式,处理数据时间很快,整体的处理时间也快了很多倍吗,但是在转换成 HashMap 这边会耗时,所以还是有缺点。
请问,有没有不用转换成 HashMap,就能解决减少直接从缓存 map 中 get 的时间的方法。
一分钟,用脚趾头猜也知道Rmap肯定是每次读都请求redis,二十万次一分钟很合理,读出来内存cache到map挺合理,如果担心内存开销可以先取getAccountId()去重在把namemap拿出来