WebFlux+Lettuce读取Redis性能问题:单线程反序列化与优化
WebFlux + Redis(Lettuce) 性能优化实践:解决单线程反序列化瓶颈
测试WebFlux读取Redis数据时发现,WebFlux会使用Lettuce的单线程(例如lettuce-ioEventLoop-5-1)完成读取及反序列化操作,耗时主要集中在反序列化环节,无法利用多核CPU的优势。根据Lettuce官方文档,可通过配置ClientOptions优化该问题,以下是具体配置过程及性能对比:
原代码实现
Controller代码
@GetMapping(value = "/{testName}", produces = MediaType.APPLICATION_JSON_VALUE) public Mono<Test> getTest(@PathVariable String testName) { return testService.getCachedTest(testName) .log(); }
Redis配置类(原)
@Configuration public class RedisConfig { @Bean public ReactiveRedisOperations<String, Test> redisOperations(ReactiveRedisConnectionFactory reactiveRedisConnectionFactory) { Jackson2JsonRedisSerializer<Test> serializer = new Jackson2JsonRedisSerializer<>(Test.class); RedisSerializationContext.RedisSerializationContextBuilder<String, Test> builder = RedisSerializationContext.newSerializationContext(new Jackson2JsonRedisSerializer<>(Test.class)); RedisSerializationContext<String, Test> context = builder .key(new StringRedisSerializer()) .value(serializer) .build(); return new ReactiveRedisTemplate<>(reactiveRedisConnectionFactory, context); } }
优化后的Redis配置类
通过自定义LettuceConnectionFactory并配置ClientOptions,开启publishOnScheduler参数,让反序列化操作脱离Lettuce的IO线程,交由调度器处理以利用多核优势:
@Configuration public class RedisConfig { @Bean public ReactiveRedisOperations<String, Pokemon> redisOperations(ReactiveRedisConnectionFactory reactiveRedisConnectionFactory) { Jackson2JsonRedisSerializer<Pokemon> serializer = new Jackson2JsonRedisSerializer<>(Pokemon.class); RedisSerializationContext.RedisSerializationContextBuilder<String, Pokemon> builder = RedisSerializationContext.newSerializationContext(new Jackson2JsonRedisSerializer<>(Pokemon.class)); RedisSerializationContext<String, Pokemon> context = builder .key(new StringRedisSerializer()) .value(serializer) .build(); return new ReactiveRedisTemplate<>(reactiveRedisConnectionFactory, context); } @Bean public LettuceConnectionFactory lettuceConnectionFactory() { RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration("localhost", 6379); ClientOptions clientOptions = ClientOptions.builder() .publishOnScheduler(true) .build(); LettuceClientConfiguration clientConfiguration = LettuceClientConfiguration.builder() .clientOptions(clientOptions) .build(); return new LettuceConnectionFactory(redisStandaloneConfiguration, clientConfiguration); } }
性能对比数据
配置前响应时间统计
"http.response_time": { "min": 2, "max": 33, "count": 8330, "mean": 8.4, "p50": 6, "median": 6, "p75": 12.1, "p90": 16.9, "p95": 19.1, "p99": 22.9, "p999": 27.9 }
配置后响应时间统计
"http.response_time": { "min": 3, "max": 47, "count": 8330, "mean": 4.7, "p50": 4, "median": 4, "p75": 5, "p90": 6, "p95": 7, "p99": 8.9, "p999": 19.9 }
优化后在多核机器上性能大幅提升,平均响应时间从8.4ms降至4.7ms,各分位响应时间也明显优化。
内容的提问来源于stack exchange,提问作者Jitesh
相关产品推荐
相关产品推荐

