前言
通过异步化从串行处理转为并行处理实现减少处理时间。
t1 + t2 + t3 -> max(t1, t2, t3)
通过Reddision客户端连接redis服务器时需要经过一系列的处理(认证、数据库选择、ping...),这些操作的特点是不互相依赖,具有无状态性。因此可以以并行执行的方式节省连接时间。
Reactive框架的使用
Reactive与RxJava2类型,是一个封装良好的异步框架。Redisson学习的Netty对Java的Future接口进行了加强,自定义了RFuture接口
Java的Future的缺点
TBC
RPromise
继承了RFuture接口,增加了boolean trySuccess(T result)和boolean tryFailure(Throwable cause)方法,程序中通过它们来触发事件的成功或失败监听方法。
BaseConnectionHandler源码
public abstract class BaseConnectionHandler<C extends RedisConnection> extends ChannelInboundHandlerAdapter {
final RedisClient redisClient;
final RPromise<C> connectionPromise = new RedissonPromise<C>();
C connection;
public BaseConnectionHandler(RedisClient redisClient) {
super();
this.redisClient = redisClient;
}
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
if (connection == null) {
connection = createConnection(ctx);
}
super.channelRegistered(ctx);
}
abstract C createConnection(ChannelHandlerContext ctx);
@Override
public void channelActive(final ChannelHandlerContext ctx) {
List<RFuture<Object>> futures = new ArrayList<RFuture<Object>>();
RedisClientConfig config = redisClient.getConfig();
if (config.getPassword() != null) {
RFuture<Object> future = connection.async(RedisCommands.AUTH, config.getPassword());
futures.add(future);
}
if (config.getDatabase() != 0) {
RFuture<Object> future = connection.async(RedisCommands.SELECT, config.getDatabase());
futures.add(future);
}
if (config.getClientName() != null) {
RFuture<Object> future = connection.async(RedisCommands.CLIENT_SETNAME, config.getClientName());
futures.add(future);
}
if (config.isReadOnly()) {
RFuture<Object> future = connection.async(RedisCommands.READONLY);
futures.add(future);
}
if (config.getPingConnectionInterval() > 0) {
RFuture<Object> future = connection.async(RedisCommands.PING);
futures.add(future);
}
if (futures.isEmpty()) {
ctx.fireChannelActive();
connectionPromise.trySuccess(connection);
return;
}
final AtomicBoolean retry = new AtomicBoolean();
final AtomicInteger commandsCounter = new AtomicInteger(futures.size());
for (RFuture<Object> future : futures) {//由于是取最长的时间,所以可以直接for循环
future.onComplete((res, e) -> {
if (e != null) {
if (e instanceof RedisLoadingException) {
if (retry.compareAndSet(false, true)) {
ctx.executor().schedule(() -> {
channelActive(ctx);
}, 1, TimeUnit.SECONDS);
}
return;
}
connection.closeAsync();
connectionPromise.tryFailure(e);
return;
}
if (commandsCounter.decrementAndGet() == 0) {
//只有在所有的command执行完后,才会处理ChannelPipeline中下一个inboundHandler的channelActive方法
ctx.fireChannelActive();
//触发成功事件监听器的监听方法,并把connection对象传递过去
connectionPromise.trySuccess(connection);
}
});
}
}
}