lettuce执行原理

io.lettuce.core.protocol.AsyncCommand 命令
io.lettuce.core.FutureSyncInvocationHandler 执行具体command命令的地方
io.lettuce.core.protocol.CommandHandler 向redis服务器发送指令/从redis服务器那儿接收指令

lettuce客户端通过io.lettuce.core.protocol.CommandHandler向redis服务器发送指令,并接收redis服务器返回的消息
底层是通过Netty和redis进行通信
io.lettuce.core.protocol.CommandHandler就是一个channelHandler,负责发送\接收消息,CommandHandler维护了一个stack(存放AsyncCommand的队列)。
当CommandHandler往redis服务器发送一个指令时会同时往stack入栈这个指令(AsyncCommand),当CommandHandler接收到redis服务器的消息时从stack出栈一个AsyncCommand,
根据接收到的消息内容设置AsyncCommand命令的结果。
io.lettuce.core.protocol.AsyncCommand是一个CompletableFuture,当应用向redis发送命令时,会将命令封装成AsyncCommand,然后等待执行结果,这个结果就是等待CommandHandler
在接收redis消息时解析内容并将结果返回给AsyncCommand。

 

发送指令 
=====io.lettuce.core.FutureSyncInvocationHandler
@Override
    protected Object handleInvocation(Object proxy, Method method, Object[] args) throws Throwable {

        try {

            Method targetMethod = this.translator.get(method);
            Object result = targetMethod.invoke(asyncApi, args);

            if (result instanceof RedisFuture<?>) {

                RedisFuture<?> command = (RedisFuture<?>) result;

                if (!isTxControlMethod(method.getName(), args) && isTransactionActive(connection)) {
                    return null;
                }

                long timeout = getTimeoutNs(command);
                
                //等待指令执行结果
                return Futures.awaitOrCancel(command, timeout, TimeUnit.NANOSECONDS);
            }

            return result;
        } catch (InvocationTargetException e) {
            throw e.getTargetException();
        }

======io.lettuce.core.internal.Futures
 public static <T> T awaitOrCancel(RedisFuture<T> cmd, long timeout, TimeUnit unit) {

        try {
            if (timeout > 0 && !cmd.await(timeout, unit)) {
                cmd.cancel(true);
                throw ExceptionFactory.createTimeoutException(Duration.ofNanos(unit.toNanos(timeout)));
            }
            return cmd.get();
        } catch (Exception e) {
            throw Exceptions.bubble(e);
        }
    }

====向redis发送指令
====io.lettuce.core.protocol.CommandHandler
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {

        if (debugEnabled) {
            logger.debug("{} write(ctx, {}, promise)", logPrefix(), msg);
        }

        if (msg instanceof RedisCommand) {
            //向redis发送指令,并将RedisCommand入栈到stack中
            writeSingleCommand(ctx, (RedisCommand<?, ?, ?>) msg, promise);
            return;
        }

        if (msg instanceof List) {

            List<RedisCommand<?, ?, ?>> batch = (List<RedisCommand<?, ?, ?>>) msg;

            if (batch.size() == 1) {

                writeSingleCommand(ctx, batch.get(0), promise);
                return;
            }

            writeBatch(ctx, batch, promise);
            return;
        }

        if (msg instanceof Collection) {
            writeBatch(ctx, (Collection<RedisCommand<?, ?, ?>>) msg, promise);
        }
    }

private void addToStack(RedisCommand<?, ?, ?> command, ChannelPromise promise) {

        try {

            validateWrite(1);

            if (command.getOutput() == null) {
                // fire&forget commands are excluded from metrics
                complete(command);
            }

            RedisCommand<?, ?, ?> redisCommand = potentiallyWrapLatencyCommand(command);

            if (promise.isVoid()) {
                stack.add(redisCommand);
            } else {
                promise.addListener(AddToStack.newInstance(stack, redisCommand));
            }
        } catch (Exception e) {
            command.completeExceptionally(e);
            throw e;
        }
    }
接收redis消息
=====io.lettuce.core.protocol.CommandHandler
protected void decode(ChannelHandlerContext ctx, ByteBuf buffer) throws InterruptedException {

        if (pristine) {

            if (stack.isEmpty() && buffer.isReadable() && !isPushDecode(buffer)) {

                if (debugEnabled) {
                    logger.debug("{} Received response without a command context (empty stack)", logPrefix());
                }

                if (consumeResponse(buffer)) {
                    pristine = false;
                }

                return;
            }
        }

        while (canDecode(buffer)) {

            if (isPushDecode(buffer)) {

                if (pushOutput == null) {
                    pushOutput = new PushOutput<>(ByteBufferCopyCodec.INSTANCE);
                }

                try {
                    if (!decode(ctx, buffer, pushOutput)) {
                        hasDecodeProgress = true;
                        decodeBufferPolicy.afterPartialDecode(buffer);
                        return;
                    }

                } catch (Exception e) {

                    ctx.close();
                    throw e;
                }

                hasDecodeProgress = false;
                PushOutput<ByteBuffer, ByteBuffer> output = pushOutput;
                pushOutput = null;
                notifyPushListeners(output);
            } else {

                //从stack出栈一个命令 并将接收的消息内容设置到command的结果里
                RedisCommand<?, ?, ?> command = stack.peek();
                if (debugEnabled) {
                    logger.debug("{} Stack contains: {} commands", logPrefix(), stack.size());
                }

                pristine = false;

                try {

                    if (!decode(ctx, buffer, command)) {
                        hasDecodeProgress = true;
                        decodeBufferPolicy.afterPartialDecode(buffer);
                        return;
                    }
                } catch (Exception e) {

                    ctx.close();
                    throw e;
                }

                hasDecodeProgress = false;
                if (isProtectedMode(command)) {
                    onProtectedMode(command.getOutput().getError());
                } else {

                    if (canComplete(command)) {
                        stack.poll();

                        try {
                            if (debugEnabled) {
                                logger.debug("{} Completing command {}", logPrefix(), command);
                            }                            
                            complete(command);
                        } catch (Exception e) {
                            logger.warn("{} Unexpected exception during request: {}", logPrefix, e.toString(), e);
                        }
                    }
                }
                afterDecode(ctx, command);
            }
        }

        decodeBufferPolicy.afterDecoding(buffer);
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值