我正在为一个新项目编写一些基准测试,并且遇到了一个问题,即生菜(版本5.1.3)和下面的代码使用了mget:
@Override
public Set<V> getKeys(final Set<Long> keySet) {
try {
return asyncCommands.mget(keySet.toArray(new Long[0])).get(
5, TimeUnit.SECONDS
).stream().map(keyValue -> keyValue.getValue()).collect(Collectors.toSet());
} catch (Exception e) {
throw new RuntimeException(e);
}
比自己使用流水线要慢得多(例如慢100倍以上):
List<RedisFuture<V>> futures = new ArrayList<>(keySet.size());
keySet.forEach(
key -> futures.add(asyncCommands.get(key))
);
asyncCommands.flushCommands();
LettuceFutures.awaitAll(5, TimeUnit.SECONDS,
futures.toArray(new RedisFuture[0]));
final Set<V> collect = futures.stream().map(
future -> {
try {
return future.get(1, TimeUnit.SECONDS);
} catch (Exception e) {
log.warn("", e);
throw new RuntimeException();
}
}
).filter(
Objects::nonNull
).collect(Collectors.toSet());
return collect;
与redis服务器报告的结果相比,这两种方法看起来都相当慢,但是那里可能还有其他因素。 javadocs说该mget应该使用流水线技术,为什么它比我自己做管道时慢得多?我在做什么不对?
编辑:对于mget,我启用了autoflush命令,对于流水线则禁用了它。
更新:发现性能降低的根源是速度慢的编解码器,当编解码器速度慢时,有什么办法可以提高整体吞吐量吗?