public <T> Mono<T> eval(RedisScript<T> script, int keyLength, ByteBuf... keys) {
        return Mono.defer(() -> {
            ByteBuf key;
            for (int i = 0, length = keys.length; i < length; i++) {
                key = keys[i];
                if (key != null) {
                    keys[i] = ByteBufUtil.ensureByteBufRefCnfCorrect(key)
                            .retain();
                }
            }
            return (Mono<T>) commands
                    .createFlux(() -> commandBuilder
                            .evalsha(script.digest(), script.outputType(), keys, keyLength))
                    .onErrorResume(e -> {
                        if (ThrowableUtil.contains(e, RedisNoScriptException.class)) {
                            return commands.createFlux(() -> commandBuilder
                                    .eval(script.script(), script.outputType(), keys, keyLength));
                        }
                        return Flux.error(e);
                    })
                    .doFinally(signal -> ReferenceCountUtil.ensureReleased(keys))
                    .single();
        });
    }
@param keyLength the real key length
turms-server-common/src/main/java/im/turms/server/common/storage/redis/TurmsRedisClient.java