问题

SpringWebFlux项目,使用的Redis客户端是Lettuce(基于异步),在Spring中封装了两种操作Redis的模板 RedisTemplateReactiveRedisTemplate ,正常情况下,异步编程要使用 ReactiveRedisTemplate ,那么可以在项目中使用 RedisTemplate 进行redis的操作吗?为什么?

答案

可以使用 RedisTemplate 在异步代码中进行操作

1
2
3
4
@Autowried
private StringRedisTemplate redisTemplate;

String value = redisTemplate.opsForValue().get(key);

追根溯源

先来明确一下应用与Redis的交互流程

Redis交互流程

  1. 获取连接
  2. 执行命令
  3. 返回结果

源码追踪

1
String value = redisTemplate.opsForValue().get(key);

以下以redis的get命令为例进行解析,get方法是通过 RedisTemplateValueOperations 属性进行处理的,因为 ValueOperations 是一个接口,要从其实现类 DefaultValueOperations 的get方法进行解析,直接上图

Figure 1: 整体流程图

Figure 1: 整体流程图

关键点解析

  • 第1-5步只是为了获取Redis连接

    getConnection是为了获取具体的底层redis命令,项目使用Lettuce且为String操作,此处获取的连接为 LettuceStringCommands

  • 第6步是命令执行触发点

    它调用了执行DefaultValueOperations.execute(ValueDeserializingRedisCallback)方法调用时方法参数ValueDeserializingRedisCallback的实现方法inRedis,由此转入到真正的命令执行阶段

  • 第9步获取API

    LettuceConnection获取的是通过调用StatefulConnection.async()方法获取的异步API

  • 第12步进行返回处理

    LettuceConnection的doInvoke方法进行了LettuceInvoker的返回处理,在里面看到的是调用了feture.get()方法使用等待的方式来实现了异步转同步的调用

获取连接阶段与执行命令阶段图示

更近一步,可以把 获取连接阶段执行命令阶段 分开来,看图更加清晰

Figure 2: 获取连接

Figure 2: 获取连接

Figure 3: 命令执行

Figure 3: 命令执行

总结

在Springwebflux项目中可以使用RedisTemplate进行对Redis API的同步调用,其内部实现是future.get()方法