【c++中间件】redis介绍 && redis-plus-plus库使用

文章目录

  • [Ⅰ. Redis 介绍](#Ⅰ. Redis 介绍)
  • [Ⅱ. Redis 的安装与操作](#Ⅱ. Redis 的安装与操作)
  • [Ⅲ. 安装 redis-plus-plus](#Ⅲ. 安装 redis-plus-plus)
  • [Ⅳ. 字符串键值对操作接口 && 使用](#Ⅳ. 字符串键值对操作接口 && 使用)

Ⅰ. Redis 介绍

RedisRemote Dictionary Server )是一个开源的高性能键值对(key-value )数据库。它通常用作数据结构服务器,因为除了基本的键值存储功能外,Redis 还支持多种类型的数据结构,如字符串(strings )、哈希(hashes )、列表(lists )、集合(sets )、有序集合(sorted sets)以及范围查询、位图、超日志和地理空间索引等。

​ 以下是 Redis 的一些主要特性:

  1. 内存中数据库Redis 将所有数据存储在内存中,这使得读写速度非常快。

  2. 持久化 :尽管 Redis 是内存数据库,但它提供了持久化选项,可以将内存中的数据保存到磁盘上,以防系统故障导致数据丢失。

  3. 支持多种数据结构Redis 不仅支持基本的键值对,还支持列表、集合、有序集合等复杂的数据结构。

  4. 原子操作Redis 支持原子操作,这意味着多个操作可以作为一个单独的原子步骤执行,这对于并发控制非常重要。

  5. 发布/订阅功能Redis 支持发布订阅模式,允许多个客户端订阅消息,当消息发布时,所有订阅者都会收到消息。

  6. 高可用性 :通过 Redis 哨兵(Sentinel)和 Redis 集群,Redis 可以提供高可用性和自动故障转移。

  7. 复制Redis 支持主从复制,可以提高数据的可用性和读写性能。

  8. 事务Redis 提供了事务功能,可以保证一系列操作的原子性执行。

  9. Lua 脚本Redis 支持使用 Lua 脚本进行复杂的数据处理,可以在服务器端执行复杂的逻辑。

  10. 客户端库Redis 拥有丰富的客户端库,支持多种编程语言,如 PythonRubyJavaC# 等。

  11. 性能监控Redis 提供了多种监控工具和命令,可以帮助开发者监控和优化性能。

  12. 易于使用Redis 有一个简单的配置文件和命令行界面,使得设置和使用变得容易。Redis 广泛用于缓存、会话存储、消息队列、排行榜、实时分析等领域。由于其高性能和灵活性,Redis 成为了现代应用程序中非常流行的数据存储解决方案之一。

Ⅱ. Redis 的安装与操作

安装命令

shell 复制代码
sudo apt install redis -y

​ 此外,在 /etc/redis/redis.conf 中可以看到 redis 的默认端口为 6379,如下图所示:

设置支持远程连接(可选)

/etc/redis/redis.conf 文件中修改以下内容即可实现远程连接:

  • 修改 bind 127.0.0.1bind 0.0.0.0
  • 修改 protected-mode yesprotected-mode no

操作 redis

shell 复制代码
sudo service redis-server start    # 启动redis服务
sudo service redis-server stop	   # 停止redis服务
sudo service redis-server restart  # 重启redis服务
sudo service redis-server status   # 查看redis状态

Ⅲ. 安装 redis-plus-plus

C++ 操作 redis 的库有很多,这里我们选用 redis-plus-plus,这个库的功能强大,使用简单,它的 Github 地址: https://github.com/sewenew/redis-plus-plus。

​ 在安装 redis-plus-plus 之前,我们得先安装 hiredis,因为 redis-plus-plus 是基于 hiredis 实现的,而 hiredis 是一个 C 语言实现的 redis 客户端,安装命令如下所示:

shell 复制代码
sudo apt install libhiredis-dev -y

​ 然后就可以下载安装 redis-plus-plus 了:

shell 复制代码
git clone https://github.com/sewenew/redis-plus-plus.git
cd redis-plus-plus && mkdir build && cd build
cmake -DCMAKE_INSTALL_PREFIX=/usr ..
make
sudo make install

​ 构建成功后 ls /usr/include/sw/redis++/ 即可看到这些头文件!

​ 还会在 /usr/lib/ 中多出一系列 libredis 库文件!

Ⅳ. 字符串键值对操作接口 && 使用

redis 本身支持很多数据类型的键值对,但是在聊天室项目中只涉及到了字符串键值对的操作,因此这里主要介绍字符串键值对的基础操作。

​ 注意:在使用 redispp 的时候,需要包含头文件:#include <sw/redis++/redis.h> ,然后链接动态库:-lhiredis -lredis++

cpp 复制代码
namespace sw {
    namespace redis {

        // 连接选项结构体,用于设置 Redis 连接的相关参数
        struct ConnectionOptions
        {
            std::string host; 			 // Redis 服务器的主机地址
            int port = 6379;  			 // Redis 服务器的端口,默认是 6379
            std::string path; 			 // Redis 连接的 Unix 套接字路径(如果有的话)
            std::string user = "default"; // Redis 用户名,默认为 "default"
            std::string password; 		 // Redis 密码
            int db = 0; 				// Redis 数据库索引,默认为 0 号数据库
            bool keep_alive = false; 	 // 是否启用持久连接
        };

        // 连接池选项结构体,设置 Redis 连接池的相关参数
        struct ConnectionPoolOptions {
            std::size_t size = 1; // 连接池中最大连接数量,默认为 1
        };

        // Redis 操作类,提供与 Redis 服务器交互的方法
        class Redis 
        {
        public:
            // 构造函数,使用 URI 初始化 Redis 连接
            // 例如:'tcp://127.0.0.1:6379'
            explicit Redis(const std::string &uri);

            // 构造函数,使用 ConnectionOptions 和 ConnectionPoolOptions 初始化 Redis 连接
            explicit Redis(const ConnectionOptions &connection_opts,
                           const ConnectionPoolOptions &pool_opts = {});

            // 删除当前数据库中的所有数据,async 标志表示是否异步执行
            void flushdb(bool async = false);

            // 删除指定的键值对,返回被删除的键值对数量
            long long del(const StringView &key);

            // 判断指定的键值对是否存在,返回 1 存在,0 不存在
            long long exists(const StringView &key);

            // 获取指定键的值,返回一个 OptionalString(可能为空)
            OptionalString get(const StringView &key);

            // 存储一个键值对,并设置可选的过期时间(毫秒),ttl 为 0 表示不设置超时
            bool set(const StringView &key,
                     const StringView &val,
                     const std::chrono::milliseconds &ttl = 
                         std::chrono::milliseconds(0), // 默认为 0,即不设置超时
                     UpdateType type = UpdateType::ALWAYS);

            // 设置键值对并指定过期时间(秒)
            void setex(const StringView &key,
                       long long ttl,  // 过期时间(秒)
                       const StringView &val);

            // 向一个列表的尾部插入元素
            long long rpush(const StringView &key, const StringView &val);

            // 向一个列表的头部插入元素
            long long lpush(const StringView &key, const StringView &val);

            // 向列表的尾部插入多个元素(使用迭代器)
            long long rpush(const StringView &key, 
                             Input first, Input last);

            // 获取列表中指定范围内的元素,输出结果通过 Output 传递
            void lrange(const StringView &key, 
                        long long start, long long stop, Output output);
        };
    } 
}

测试样例

​ 这里只进行字符串键值对的增删改查操作以及数据的生命周期设置!

cpp 复制代码
#include <sw/redis++/redis.h>
#include <gflags/gflags.h>
#include <iostream>
#include <thread>

DEFINE_string(ip, "127.0.0.1", "这是服务器的IP地址,格式:127.0.0.1");
DEFINE_int32(port, 6379, "这是服务器的端口, 格式: 6379");
DEFINE_int32(db, 0, "库的编号:默认0号");
DEFINE_bool(keep_alive, true, "是否进行长连接保活");

void print(sw::redis::Redis &client) 
{
    auto user1 = client.get("会话ID1");
    if (user1) std::cout << *user1 << std::endl;
    auto user2 = client.get("会话ID2");
    if (user2) std::cout << *user2 << std::endl;
    auto user3 = client.get("会话ID3");
    if (user3) std::cout << *user3 << std::endl;
    auto user4 = client.get("会话ID4");
    if (user4) std::cout << *user4 << std::endl;
    auto user5 = client.get("会话ID5");
    if (user5) std::cout << *user5 << std::endl;
}

void add_string(sw::redis::Redis &client) 
{
    client.set("会话ID1", "用户ID1");
    client.set("会话ID2", "用户ID2");
    client.set("会话ID3", "用户ID3");
    client.set("会话ID4", "用户ID4");
    client.set("会话ID5", "用户ID5");

    client.del("会话ID3");

    client.set("会话ID5", "用户ID555");  // 数据已存在则进行修改,不存在则新增

    print(client);
}

void expired_test(sw::redis::Redis &client) {
    // 这次的新增,数据其实已经有了,因此本次是修改
    // 不仅仅修改了val,而且还给键值对新增了过期时间
    client.set("会话ID1", "用户ID1111", std::chrono::milliseconds(1000));

    print(client);
    std::cout << "------------休眠2s-----------\n";
    std::this_thread::sleep_for(std::chrono::seconds(2));
    print(client);
}

void list_test(sw::redis::Redis &client) {
    client.rpush("群聊1", "成员1");
    client.rpush("群聊1", "成员2");
    client.rpush("群聊1", "成员3");
    client.rpush("群聊1", "成员4");
    client.rpush("群聊1", "成员5");

    std::vector<std::string> users;
    client.lrange("群聊1", 0, -1, std::back_inserter(users));

    for (auto user : users) {
        std::cout << user << std::endl;
    }
}

int main(int argc, char *argv[])
{
    google::ParseCommandLineFlags(&argc, &argv, true);
    
    // 1. 构造连接选项,实例化Redis对象,连接服务器
    sw::redis::ConnectionOptions opts;
    opts.host = FLAGS_ip;
    opts.port = FLAGS_port;
    opts.db = FLAGS_db;
    opts.keep_alive = FLAGS_keep_alive;
    sw::redis::Redis client(opts);

    // 2. 添加字符串键值对,删除字符串键值对,获取字符串键值对
    add_string(client);

    // 3. 实践控制数据有效时间的操作
    expired_test(client);

    // 4. 列表的操作,主要实现数据的右插,左获取
    std::cout << "--------------------------\n";
    list_test(client);
    return 0;
}

makefile 文件:

makefile 复制代码
main : main.cc
	g++ -std=c++17 $^ -o $@ -lhiredis -lredis++ -lgflags
相关推荐
q***816429 分钟前
【Redis】centos7 systemctl 启动 Redis 失败
数据库·redis·缓存
永不停转33 分钟前
关于 QGraphicsItemGroup 内部项目发生变化后group重新定位的问题
c++·qt
IT永勇1 小时前
C++设计模式-装饰器模式
c++·设计模式·装饰器模式
Murphy_lx2 小时前
std_ofstream
c++
草莓熊Lotso2 小时前
红黑树从入门到进阶:4 条规则如何筑牢 O (logN) 效率根基?
服务器·开发语言·c++·人工智能·经验分享·笔记·后端
啊董dong2 小时前
课后作业-2025年11月23号作业
数据结构·c++·算法·深度优先·noi
带鱼吃猫2 小时前
Linux系统:策略模式实现自定义日志功能
linux·c++
zzzsde2 小时前
【C++】C++11(1):右值引用和移动语义
开发语言·c++·算法
学困昇2 小时前
C++11中的包装器
开发语言·数据结构·c++·c++11