7 CHN 17 Redis
ProTankerAlfa edited this page 2024-05-20 01:29:57 -03:00
This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

English | 简体中文

Drogon支持RedisRedis是一种非常快速的内存数据存储。 可以用作数据库缓存或消息代理。 与Drogon中其他组件一樣Redis的操作是异步的。 这确保了Drogon即使在重负载下也能以非常高的并发性运行。

Redis支持依赖于hiredis库。 如果在构建Drogon时hiredis不可用则Redis支持将不可用。

创建客户端

Redis客户端可以通过以下方式以方式创建

app().createRedisClient("127.0.0.1", 6379);
...
// After app.run()
RedisClientPtr redisClient = app().getRedisClient();

另外与Database客户端一样Redis客户端也支持config文件配置也支持配置成Fast模式具体配置如下

    "redis_clients": [
        {
            //name: 客户端名字, 默认值是'default'
            //"name":"",
            //host: 服务端IP, 默认值是127.0.0.1
            "host": "127.0.0.1",
            //port: 服务端端口号, 默认值是6379
            "port": 6379,
            //passwd: 密码,默认为空
            "passwd": "",
            //db index: 默认值是0
            "db": 0,
            //is_fast: 默认值是false, 是否是fast模式如果为true会以更高效的方式运行但是只能在IO线程或主线程中使用, 并且不能使用同步接口。
            "is_fast": false,
            //number_of_connections: 连接数, 默认值是1, 如果is_fast为true, 该数字表示每个IO线程或主线程内的连接数, 否则表示该客户端所有连接数
            "number_of_connections": 1,
            //timeout: 超时值,默认值是-1.0, 单位是秒表示一条命令的超时时间超过这个时间未得到结果将返回超时错误0或者负值表示没有超时限制
            "timeout": -1.0
        }
    ]

使用Redis

execCommandAsync以异步方式执行Redis命令。 它至少需要3个参数第一个和第二个是在Redis命令成功或失败时调用的回调。 第三是命令本身。 该命令可以是C风格的格式字符串。 其余部分是格式字符串的参数。 例如,要设置namedrogon

redisClient->execCommandAsync(
    [](const drogon::nosql::RedisResult &r) {},
    [](const std::exception &err) {
        LOG_ERROR << "something failed!!! " << err.what();
    },
    "set name drogon");

或者将myid设置为587d-4709-86e4

redisClient->execCommandAsync(
    [](const drogon::nosql::RedisResult &r) {},
    [](const std::exception &err) {
        LOG_ERROR << "something failed!!! " << err.what();
    },
    "set myid %s", "587d-4709-86e4");

同样的execCommandAsync也可以从Redis取得数据。

redisClient->execCommandAsync(
    [](const drogon::nosql::RedisResult &r) {
        if (r.type() == RedisResultType::kNil)
            LOG_INFO << "Cannot find variable associated with the key 'name'";
        else
            LOG_INFO << "Name is " << r.asString();
    },
    [](const std::exception &err) {
        LOG_ERROR << "something failed!!! " << err.what();
    },
    "get name");

Redis事务

Redis事务允许在一个步骤中执行多个命令。 事务中的所有命令都按顺序执行,其他客户端的命令不会在事务中间执行。 注意redis的事务不是原子操作也就是说收到EXEC命令后进入事务执行事务中任意命令执行失败其余的命令依然被执行。redis事务没有回滚操作。

newTransactionAsync方法创建一个新事务。 然后就可以像普通的RedisClient一样使用事务。 最后RedisTransaction::execute方法执行事务。

redisClient->newTransactionAsync([](const RedisTransactionPtr &transPtr) {
    transPtr->execCommandAsync(
        [](const drogon::nosql::RedisResult &r) { /* this command works */ },
        [](const std::exception &err) { /* this command failed */ },
    "set name drogon");

    transPtr->execute(
        [](const drogon::nosql::RedisResult &r) { /* transaction worked */ },
        [](const std::exception &err) { /* transaction failed */ });
});

协程

Redis客户端也支持协程. 需要GCC 11或者更新的编译器并且使用cmake -DCMAKE_CXX_FLAGS="-std=c++20" 来使能它。見协程取得细节

try
{
    auto transaction = co_await redisClient->newTransactionCoro();
    co_await transaction->execCommandCoro("set zzz 123");
    co_await transaction->execCommandCoro("set mening 42");
    co_await transaction->executeCoro();
}
catch(const std::exception& e)
{
    LOG_ERROR << "Redis failed: " << e.what();
}

测试框架