《Redis库基础使用》
一、特点
使用 Redis 核心是为了提升数据读写速度,解决传统数据库在高并发场景下的性能瓶颈。
为什么用 Redis?
- 速度极快:数据存储在内存中,读写速度比磁盘数据库快 10-100 倍,能轻松应对每秒数万次的请求。
- 支持多场景:不仅能存简单的键值对,还支持列表、哈希、集合等复杂结构,可满足缓存、计数、排队等多种需求。
- 降低数据库压力:把高频访问的数据放在 Redis 中,避免大量请求直接冲击 MySQL 等数据库,保护后端服务稳定。
什么情况用 Redis?
- 高频数据缓存:比如电商商品详情、用户登录信息,用户再次访问时直接从 Redis 读取,无需查数据库。
- 实时计数统计:如文章阅读量、视频播放量、商品库存,Redis 支持原子操作,能确保计数准确不重复。
- 分布式锁 / 共享数据:在多服务器集群中,用 Redis 实现分布式锁,防止多个服务同时修改同一数据;或存储全局共享配置。
- 消息队列 / 排行榜:用 Redis 的列表结构做简单消息队列,用有序集合实现实时排行榜(如游戏积分排名)。
二、安装 redis
ubuntu下:
apt install redis -y
查看redis是否启动
sudo netstat -antpu | grep 6379
启动 Redis 服务
service redis-server start
停止 Redis 服务
service redis-server stop
重启 Redis 服务
service redis-server restart
开机自启动设置
sudo systemctl enable redis-server
三、安装 C++ Redis 客户端库
在 C++ 开发中,若需与 Redis 交互,需借助 C++ Redis 客户端库(Redis 原生不提供 C++接口,需依赖第三方库封装底层 C 接口或实现独立协议交互)。以下从核心库介绍、典型功能与示例、选型建议三方面展开,帮助你快速理解 C++ 操作 Redis 的方式。
Github 地址: https://github.com/sewenew/redis-plus-plus
hiredis 是一个 C 语言实现的 redis 客户端.
因此需要先安装 hiredis. 直接使用包管理器安装即可.
apt install libhiredis-dev
下载 redis-plus-plus 源码
git clone https://github.com/sewenew/redis-plus-plus.git
也可在官网下载之后拖进vs进行解压
编译/安装 redis-plus-plus
cd redis-plus-plus-master/
mkdir build
cd build
cmake -DCMAKE_INSTALL_PREFIX=/usr ..
make
sudo make install
构建成功后, 会在 /usr/include/ 中多出 sw 目录, 并且内部包含 redis-plusplus 的一系列头文件.
四、接口预览
redis 本身支持很多数据类型的键值对,但是在聊天室项目中只涉及到了字符串键值对的操作,因此这里主要介绍字符串键值对的基础操作。
namespace sw {
namespace redis {struct ConnectionOptions {std::string host;int port = 6379;std::string path;std::string user = "default";std::string password;int db = 0; // 默认 0 号库bool keep_alive = false;} struct ConnectionPoolOptions {std::size_t size = 1; //最大连接数量} class Redis {// uri e.g 'tcp://127.0.0.1:6379'explicit Redis(const std::string &uri)explicit Redis(const ConnectionOptions &connection_opts,const ConnectionPoolOptions &pool_opts = {})//删除当前库中所有数据void flushdb(bool async = false);//删除指定键值对long long del(const StringView &key);//判断指定键值对是否存在long long exists(const StringView &key);//获取一个 string 键值对OptionalString get(const StringView &key);//存放一个 string 键值对,且设置过期时间-毫秒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);//向一个列表中尾插/头插 string 键值对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);// std::vector<std::string> elements;// redis.lrange("list", 0, -1,
std::back_inserter(elements));void lrange(const StringView &key,long long start, long long stop, Output output);}
}
}
五、基础操作示例
下面通过一个示例,演示 redis-plus-plus 的常用操作,包括连接 Redis、字符串操作、列表操作等。
1. 主函数初始化
#include <sw/redis++/redis.h>
#include <iostream>
#include <thread>
int main(int argc, char *argv[]) {//功能接口演示中://1. 构造连接选项,实例化Redis对象,连接服务器sw::redis::ConnectionOptions opts;opts.host = "127.0.0.1";opts.port = 6379;opts.db = 0;opts.keep_alive = true;sw::redis::Redis client(opts);//2. 添加字符串键值对,删除字符串键值对,获取字符串键值对add_string(client);//3. 实践控制数据有效时间的操作expired_test(client);//4. 列表的操作,主要实现数据的右插,左获取std::cout << "--------------------------\n";list_test(client);return 0;
}
2. ConnectionOptions
在 redis-plus-plus 库中,sw::redis::ConnectionOptions
是用于配置 Redis 连接参数的核心结构体,它封装了与 Redis 服务器建立连接所需的所有关键信息。
通过设置 ConnectionOptions 的属性,可以灵活控制连接的目标服务器、认证方式、超时时间等,是初始化 sw::redis::Redis 客户端的必要参数。
属性名 | 类型 | 说明 | 默认值 |
---|---|---|---|
host std::string | Redis 服务器的 IP 地址或主机名 | (如 “127.0.0.1”、“redis-server”) | “127.0.0.1” |
port | int | Redis 服务器的端口号 | 6379(Redis 默认端口) |
db | int | 要连接的 Redis 数据库编号(Redis 默认为 0-15 共 16 个库) | 0 |
password | std::string | 连接 Redis 服务器的密码(若服务器启用了密码认证) | 空字符串(不认证) |
keep_alive | bool | 是否启用 TCP 长连接保活机制(避免频繁断开重连) | false |
connect_timeout | std::chrono::milliseconds | 连接超时时间(超过此时长未连接成功则报错) | 0(无超时,无限等待) |
socket_timeout | std::chrono::milliseconds | 读写操作超时时间(超过此时长未完成则报错) | 0(无超时,无限等待) |
ssl | bool | 是否启用 SSL 加密连接(适用于需要加密传输的场景) | false |
unix_socket_path | std::string | Unix 域套接字路径(若通过本地套接字连接 Redis,而非 TCP) | 空字符串(不使用) |
3. 操作字符串
sw::redis::Redis client
对字符串的操作:
sw::redis::Redis 接口 | 功能说明 |
---|---|
client.set(key, value) | 设置键值对 |
client.set(key, value, std::chrono::seconds(t)) | 设置键值对并指定过期时间(t 为秒数) |
auto val = client.get(key) | 获取键的值(返回 std::optionalstd::string,空表示键不存在) |
client.del(key) | 删除键(返回被删除的键数量) |
client.expire(key, std::chrono::seconds(t)) | 为键设置过期时间(t 为秒数) |
auto ttl = client.ttl(key) | 获取键的剩余过期时间(返回毫秒数,-1 表示永不过期) |
client.incr(key) | 键的数值自增 1(键值需为整数) |
client.decr(key) | 键的数值自减 1(键值需为整数) |
新增字符串:
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);
}
4. 操作列表
sw::redis::Redis | 接口 功能说明 |
---|---|
client.rpush(list_key, val) | 从列表右侧插入元素 |
client.lpush(list_key, val) | 从列表左侧插入元素 |
client.lrange(list_key, start, end, std::back_inserter(vec)) | 获取列表中 [start, end] 范围的元素(存入 std::vector,end=-1 表示最后一个元素) |
auto val = client.lpop(list_key) | 从列表左侧弹出并返回第一个元素 |
auto val = client.rpop(list_key) | 从列表右侧弹出并返回最后一个元素 |
size_t len = client.llen(list_key) | 获取列表的长度 |
client.lrem(list_key, count, val) | 从列表中删除 count 个值为 val 的元素 |
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;}
}
5. 输出结果
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;
}