使用 boost::redis 管道传输请求/响应

问题描述 投票:0回答:1

考虑到任务 - 对与模式匹配的所有键(可能有数百万个)执行 HGETALL。

我在一个连接上获取密钥并在另一连接上同时执行 HGETALL。这仍然不能解决 HGETALL 往返延迟,我想完全摆脱它。

我想做的是使用飞行中的窗口推送 HGETALL 请求,就像没有明天一样。

我知道我可以执行一个包含多个 HGETALL-s 的请求*,但是我仍然需要等待响应并偶尔支付延迟。 *- 虽然我还没有弄清楚如何调整此类请求的响应类型,因此它的大小不是静态的。

有更好的办法吗?

我正在使用协程语法,因此现在的代码如下所示:

auto request = redis::request{};
request.push("HGETALL", key);
auto response = redis::response<std::vector<std::string>>{};
co_await conn->async_exec(request, response, asio::deferred);

谢谢!

c++ boost redis boost-asio
1个回答
0
投票

看事物,你或许能从

redis::generic_response
得到你想要的一切。这将是一些工作,但如果您知道您的目标应用程序并且命令都是相同的,您可能无需太多努力即可使其工作:

redis::request request;
for (auto const& key : keys)
    request.push("HGETALL", key);
request.push("QUIT");

redis::generic_response response;
co_await conn->async_exec(request, response, asio::deferred);

auto const& gen = response.value();
fmt::print("generic: {}\n", gen);

解释端批处理事务可能是有利的(我不是Redis专家,所以我不知道这是否会损害服务器性能):

redis::request request;
request.push("MULTI");
for (auto const& key : keys)
    request.push("HGETALL", key);
request.push("EXEC");
request.push("QUIT");

使用简单的格式化程序来显示响应的结构:

住在Coliru

#include <boost/asio.hpp>
#include <boost/redis/src.hpp>
#include <fmt/ostream.h>
#include <fmt/ranges.h>
namespace redis = boost::redis;
namespace asio  = boost::asio;

template <> struct fmt::formatter<redis::resp3::type> : fmt::ostream_formatter {};
template <> struct fmt::formatter<redis::resp3::node> : fmt::formatter<std::string> {
    template <typename FormatContext> auto format(redis::resp3::node const& node, FormatContext& ctx) const {
        return format_to(ctx.out(), "({}@{}, {}, {})", node.data_type, node.depth, node.value,
                         node.aggregate_size);
    }
};

asio::awaitable<void> use_redis(std::vector<std::string> keys) {
    auto conn = std::make_shared<redis::connection>(co_await asio::this_coro::executor);
    redis::config cfg;
    conn->async_run(cfg, {}, asio::consign(asio::detached, conn));

    {
        redis::request request;
        for (auto const& key : keys)
            request.push("HGETALL", key);
        request.push("QUIT");

        redis::generic_response response;
        co_await conn->async_exec(request, response, asio::deferred);

        fmt::print("generic: {}\n", response.value());
    }

    conn->cancel();
    conn->async_run(cfg, {}, asio::consign(asio::detached, conn));

    {
        redis::request request;
        request.push("MULTI");
        for (auto const& key : keys)
            request.push("HGETALL", key);
        request.push("EXEC");
        request.push("QUIT");

        redis::generic_response response;
        co_await conn->async_exec(request, response, asio::deferred);

        fmt::print("multi: {}\n", response.value());
    }

    conn->cancel();
}

int main() {
    asio::io_context ioc(1);
    co_spawn(ioc, use_redis({"foo", "bar"}), asio::detached);
    ioc.run();
}

本地演示:

HSET foo bar baz
HSET bar qux quuz
$ redis-cli 
127.0.0.1:6379> HGETALL foo
1) "bar"
2) "baz"
127.0.0.1:6379> HGETALL bar
1) "qux"
2) "quuuz"
127.0.0.1:6379> 


$ ./build/sotest 
generic: [(map@0, , 1), (blob_string@1, bar, 1), (blob_string@1, baz, 1), (map@0, , 1), (blob_string@1, qux, 1), (blob_string@1, quuuz, 1), (simple_string@0, OK, 1)]
multi: [(simple_string@0, OK, 1), (simple_string@0, QUEUED, 1), (simple_string@0, QUEUED, 1), (array@0, , 2), (map@1, , 1), (blob_string@2, bar, 1), (blob_string@2, baz, 1), (map@1, , 1), (blob_string@2, qux, 1), (blob_string@2, quuuz, 1), (simple_string@0, OK, 1)]
© www.soinside.com 2019 - 2024. All rights reserved.