考虑到任务 - 对与模式匹配的所有键(可能有数百万个)执行 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);
谢谢!
看事物,你或许能从
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");
使用简单的格式化程序来显示响应的结构:
#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)]