0.RESP
RESP :Redis自定义的应用层协议
优点 :
工作流程 :请求和响应之间的通信模型是一问一答 的形式
客户端给服务器发一个请求(Redis 命令 ),服务器返回一个响应
客户端和服务器只需要按照格式,构造出字符串,往socket
中写入或者从socket
中读取字符串,按照上述格式解析
1.前置依赖 – hiredis
redis-plus-plus
是基于hiredis
实现的,hiredis
是⼀个C语⾔实现的Redis客⼾端
安装 :apt install libhiredis-dev
2.安装 redis-plus-plus
3.示例:通用命令
1.Quick Start
main.cc
:# include <iostream>
# include <string>
# include <sw/redis++/redis++.h>
using namespace std;
int main ( )
{
sw:: redis:: Redis redis ( "tcp://127.0.0.1:6379" ) ;
string ret = redis. ping ( ) ;
cout << ret << endl;
return 0 ;
}
Makefile
:main:main.cc
g++ -std=c++17 -o $@ $^ -l redis++ -l hiredis -l pthread
.PHONY:clean
clean:
rm main
2.Get && Set
此处的redis.get()
返回的是一个optional
类型
optional
类型在C++14中,正式纳入标准库
因为redis.get()
会返回nil
无效值,用std::string
不方便表现nil
,而std::string*
虽然可以用nullptr
表示无效,但是返回指针又设计内存管理问题
所以综上,此处使用optional
表示"非法值"/“无效值”
void TestGetAndSet ( sw:: redis:: Redis& redis)
{
redis. flushall ( ) ;
redis. set ( "key1" , "233" ) ;
redis. set ( "key2" , "666" ) ;
redis. set ( "key3" , "888" ) ;
auto value1 = redis. get ( "key1" ) ;
if ( value1)
{
cout << "value1=" << value1. value ( ) << endl;
}
auto value2 = redis. get ( "key2" ) ;
if ( value2)
{
cout << "value2=" << value2. value ( ) << endl;
}
auto value3 = redis. get ( "key3" ) ;
if ( value2)
{
cout << "value3=" << value3. value ( ) << endl;
}
auto value4 = redis. get ( "key4" ) ;
if ( value4)
{
cout << "value4=" << value4. value ( ) << endl;
}
}
3.Exists
void TestExists ( sw:: redis:: Redis & redis)
{
redis. flushall ( ) ;
redis. set ( "key1" , "111" ) ;
redis. set ( "key3" , "111" ) ;
auto ret = redis. exists ( "key1" ) ;
cout << ret << endl;
ret = redis. exists ( "key2" ) ;
cout << ret << endl;
ret = redis. exists ( { "key1" , "key2" , "key3" } ) ;
cout << ret << endl;
}
4.Keys
void TestKeys ( sw:: redis:: Redis & redis)
{
redis. flushall ( ) ;
redis. set ( "key1" , "111" ) ;
redis. set ( "key2" , "222" ) ;
redis. set ( "key3" , "333" ) ;
redis. set ( "key4" , "444" ) ;
redis. set ( "key5" , "555" ) ;
redis. set ( "key6" , "666" ) ;
vector< string> ret;
auto it = std:: back_inserter ( ret) ;
redis. keys ( "*" , it) ;
PrintContainer ( ret) ;
}
5.Expire && TTL
void TestExpireAndTTL ( sw:: redis:: Redis & redis)
{
redis. flushall ( ) ;
redis. set ( "key" , "111" ) ;
redis. expire ( "key" , 10 s) ;
std:: this_thread:: sleep_for ( 3 s) ;
auto time = redis. ttl ( "key" ) ;
cout << time << endl;
}
6.Type
void TestType ( sw:: redis:: Redis& redis)
{
redis. flushall ( ) ;
redis. set ( "key1" , "111" ) ;
string result = redis. type ( "key" ) ;
cout << "key1: " << result << endl;
redis. lpush ( "key2" , "111" ) ;
result = redis. type ( "key2" ) ;
cout << "key2: " << result << endl;
redis. hset ( "key3" , "aaa" , "111" ) ;
result = redis. type ( "key3" ) ;
cout << "key3: " << result << endl;
redis. sadd ( "key4" , "aaa" ) ;
result = redis. type ( "key4" ) ;
cout << "key4: " << result << endl;
redis. zadd ( "key5" , "吕布" , 99 ) ;
result = redis. type ( "key5" ) ;
cout << "key5: " << result << endl;
}
4.示例:String
1.Set with expire
void TestSetWithExpire ( Redis& redis)
{
redis. flushall ( ) ;
redis. set ( "key" , "111" , 10 s) ;
std:: this_thread:: sleep_for ( 3 s) ;
long long time = redis. ttl ( "key" ) ;
std:: cout << "time: " << time << std:: endl;
}
2.Set NX / XX
void TestSetNXAndXX ( Redis & redis)
{
redis. flushall ( ) ;
redis. set ( "key" , "111" ) ;
redis. set ( "key" , "222" , 0 s, sw:: redis:: UpdateType:: EXIST) ;
auto value = redis. get ( "key" ) ;
if ( value)
{
std:: cout << "value: " << value. value ( ) << std:: endl;
}
}
3.Mset
void TestMset ( Redis & redis)
{
redis. flushall ( ) ;
vector< pair< string, string>> keys = {
{ "key1" , "111" } ,
{ "key2" , "222" } ,
{ "key3" , "333" }
} ;
redis. mset ( keys. begin ( ) , keys. end ( ) ) ;
auto value = redis. get ( "key1" ) ;
if ( value)
{
std:: cout << "value: " << value. value ( ) << std:: endl;
}
value = redis. get ( "key2" ) ;
if ( value)
{
std:: cout << "value: " << value. value ( ) << std:: endl;
}
value = redis. get ( "key3" ) ;
if ( value)
{
std:: cout << "value: " << value. value ( ) << std:: endl;
}
}
4.Mget
void TestMget ( Redis & redis)
{
redis. flushall ( ) ;
vector< std:: pair< string, string>> keys = {
{ "key1" , "111" } ,
{ "key2" , "222" } ,
{ "key3" , "333" } } ;
redis. mset ( keys. begin ( ) , keys. end ( ) ) ;
vector< sw:: redis:: OptionalString> result;
auto it = std:: back_inserter ( result) ;
redis. mget ( { "key1" , "key2" , "key3" , "key4" } , it) ;
PrintContainerOptional ( result) ;
}
5.Getrange && Setrange
void TestRange ( Redis & redis)
{
redis. flushall ( ) ;
redis. set ( "key" , "DieKSnowK" ) ;
string result = redis. getrange ( "key" , 2 , 5 ) ;
cout << "result: " << result << endl;
redis. setrange ( "key" , 2 , "xyz" ) ;
auto value = redis. get ( "key" ) ;
cout << "value: " << value. value ( ) << endl;
}
5.示例:list
1.Push && Range
void TestPushAndRange ( Redis & redis)
{
redis. flushall ( ) ;
redis. lpush ( "key" , "111" ) ;
redis. lpush ( "key" , { "222" , "333" , "444" } ) ;
vector< string> values = { "555" , "666" , "777" } ;
redis. lpush ( "key" , values. begin ( ) , values. end ( ) ) ;
vector< string> results;
auto it = std:: back_inserter ( results) ;
redis. lrange ( "key" , 0 , - 1 , it) ;
PrintContainer ( results) ;
}
2.Pop
void TestPop ( Redis & redis)
{
redis. flushall ( ) ;
redis. rpush ( "key" , { "1" , "2" , "3" , "4" } ) ;
auto result = redis. lpop ( "key" ) ;
if ( result)
{
std:: cout << "lpop: " << result. value ( ) << std:: endl;
}
result = redis. rpop ( "key" ) ;
if ( result)
{
std:: cout << "rpop: " << result. value ( ) << std:: endl;
}
}
3.blpop
TIPS :对于std::optional
类型来说,可以直接使用->
访问optional
内部包含的元素的成员void TestBlpop ( Redis & redis)
{
redis. flushall ( ) ;
auto result = redis. blpop ( { "key" , "key2" , "key3" } , 10 s) ;
if ( result)
{
std:: cout << "key:" << result-> first << std:: endl;
std:: cout << "elem:" << result-> second << std:: endl;
}
else
{
std:: cout << "result 无效!" << std:: endl;
}
}
4.llen
void TestLlen ( Redis & redis)
{
redis. flushall ( ) ;
redis. lpush ( "key" , { "111" , "222" , "333" , "444" } ) ;
long long len = redis. llen ( "key" ) ;
cout << "len: " << len << endl;
}
6.示例:set
1.Sadd && Smembers
此处要注意保存结果的方式和之前的区别 void TestSaddAndSmembers ( Redis& redis)
{
redis. flushall ( ) ;
redis. sadd ( "key" , "111" ) ;
redis. sadd ( "key" , { "222" , "333" , "444" } ) ;
set< string> elems = { "555" , "666" , "777" } ;
redis. sadd ( "key" , elems. begin ( ) , elems. end ( ) ) ;
set< string> result;
auto it = std:: inserter ( result, result. end ( ) ) ;
redis. smembers ( "key" , it) ;
PrintContainer ( result) ;
}
2.Sismerber
void TestSismember ( Redis& redis)
{
redis. flushall ( ) ;
redis. sadd ( "key" , { "111" , "222" , "333" , "444" } ) ;
bool result = redis. sismember ( "key" , "555" ) ;
cout << "result: " << result << endl;
}
3.Scard
void TestScard ( Redis & redis)
{
redis. flushall ( ) ;
redis. sadd ( "key" , { "111" , "222" , "333" } ) ;
long long result = redis. scard ( "key" ) ;
cout << "result: " << result << endl;
}
4.Spop
void TestSpop ( Redis& redis)
{
redis. flushall ( ) ;
redis. sadd ( "key" , { "111" , "222" , "333" , "444" } ) ;
auto result = redis. spop ( "key" ) ;
if ( result)
{
std:: cout << "result: " << result. value ( ) << std:: endl;
}
else
{
std:: cout << "result 无效!" << std:: endl;
}
}
5.Sinter
void TestSinter ( Redis & redis)
{
redis. flushall ( ) ;
redis. sadd ( "key1" , { "111" , "222" , "333" } ) ;
redis. sadd ( "key2" , { "111" , "222" , "444" } ) ;
set< string> result;
auto it = std:: inserter ( result, result. end ( ) ) ;
redis. sinter ( { "key1" , "key2" } , it) ;
PrintContainer ( result) ;
}
6.Sinterstore
void TestSinterstore ( Redis & redis)
{
redis. flushall ( ) ;
redis. sadd ( "key1" , { "111" , "222" , "333" } ) ;
redis. sadd ( "key2" , { "111" , "222" , "444" } ) ;
long long len = redis. sinterstore ( "key3" , { "key1" , "key2" } ) ;
cout << "len: " << len << endl;
set< string> result;
auto it = std:: inserter ( result, result. end ( ) ) ;
redis. smembers ( "key3" , it) ;
PrintContainer ( result) ;
}
7.示例:hash
1.Hset && Hget
void TestHsetAndHget ( Redis & redis)
{
redis. flushall ( ) ;
redis. hset ( "key" , "f1" , "111" ) ;
redis. hset ( "key" , std:: make_pair ( "f2" , "222" ) ) ;
redis. hset ( "key" , { std:: make_pair ( "f3" , "333" ) ,
std:: make_pair ( "f4" , "444" ) } ) ;
vector< std:: pair< string, string>> fields = {
std:: make_pair ( "f5" , "555" ) ,
std:: make_pair ( "f6" , "666" ) } ;
redis. hset ( "key" , fields. begin ( ) , fields. end ( ) ) ;
auto result = redis. hget ( "key" , "f3" ) ;
if ( result)
{
std:: cout << "result: " << result. value ( ) << std:: endl;
}
else
{
std:: cout << "result 无效!" << std:: endl;
}
}
2.Hexists
void TestHexists ( Redis & redis)
{
redis. flushall ( ) ;
redis. hset ( "key" , "f1" , "111" ) ;
redis. hset ( "key" , "f2" , "222" ) ;
redis. hset ( "key" , "f3" , "333" ) ;
bool result = redis. hexists ( "key" , "f4" ) ;
std:: cout << "result: " << result << std:: endl;
}
3.Hdel
void TestHdel ( Redis & redis)
{
redis. flushall ( ) ;
redis. hset ( "key" , "f1" , "111" ) ;
redis. hset ( "key" , "f2" , "222" ) ;
redis. hset ( "key" , "f3" , "333" ) ;
long long result = redis. hdel ( "key" , "f1" ) ;
std:: cout << "result: " << result << std:: endl;
result = redis. hdel ( "key" , { "f2" , "f3" } ) ;
std:: cout << "result: " << result << std:: endl;
long long len = redis. hlen ( "key" ) ;
std:: cout << "len: " << len << std:: endl;
}
4.Hkeys && Hvals
void TestHkeysAndHvals ( Redis & redis)
{
redis. flushall ( ) ;
redis. hset ( "key" , "f1" , "111" ) ;
redis. hset ( "key" , "f2" , "222" ) ;
redis. hset ( "key" , "f3" , "333" ) ;
vector< string> fields;
auto itFields = std:: back_inserter ( fields) ;
redis. hkeys ( "key" , itFields) ;
PrintContainer ( fields) ;
vector< string> values;
auto itValues = std:: back_inserter ( values) ;
redis. hvals ( "key" , itValues) ;
PrintContainer ( values) ;
}
5.Hmget && Hmset
void TestHmgetAndHmset ( Redis & redis)
{
redis. flushall ( ) ;
redis. hmset ( "key" , { std:: make_pair ( "f1" , "111" ) ,
std:: make_pair ( "f2" , "222" ) ,
std:: make_pair ( "f3" , "333" ) } ) ;
vector< std:: pair< string, string>> pairs = {
std:: make_pair ( "f4" , "444" ) ,
std:: make_pair ( "f5" , "555" ) ,
std:: make_pair ( "f6" , "666" ) } ;
redis. hmset ( "key" , pairs. begin ( ) , pairs. end ( ) ) ;
vector< string> values;
auto it = std:: back_inserter ( values) ;
redis. hmget ( "key" , { "f1" , "f2" , "f3" } , it) ;
PrintContainer ( values) ;
}
8.示例:zset
1.Zadd && Zrange
zrange
支持两种主要的风格:
只查询member
, 不带score
查询member
同时带score
关键就是看插入迭代器指向的容器的类型 :
指向的容器只是包含一个string
, 就是只查询member
指向的容器包含的是一个pair
, 里面有string
和 double
, 就是查询member
同时带有score
void TestZaddAndZrange ( Redis & redis)
{
redis. flushall ( ) ;
redis. zadd ( "key" , "吕布" , 99 ) ;
redis. zadd ( "key" , { std:: make_pair ( "赵云" , 98 ) ,
std:: make_pair ( "典韦" , 97 ) } ) ;
vector< std:: pair< string, double >> members = {
std:: make_pair ( "关羽" , 95 ) ,
std:: make_pair ( "张飞" , 93 ) } ;
redis. zadd ( "key" , members. begin ( ) , members. end ( ) ) ;
vector< string> memberResults;
auto it = std:: back_inserter ( memberResults) ;
redis. zrange ( "key" , 0 , - 1 , it) ;
PrintContainer ( memberResults) ;
vector< std:: pair< string, double >> membersWithScore;
auto it2 = std:: back_inserter ( membersWithScore) ;
redis. zrange ( "key" , 0 , - 1 , it2) ;
PrintContainerPair ( membersWithScore) ;
}
2.Zcard
void TestZcard ( Redis & redis)
{
redis. flushall ( ) ;
redis. zadd ( "key" , "zhangsan" , 90 ) ;
redis. zadd ( "key" , "lisi" , 91 ) ;
redis. zadd ( "key" , "wangwu" , 92 ) ;
redis. zadd ( "key" , "zhaoliu" , 93 ) ;
long long result = redis. zcard ( "key" ) ;
std:: cout << "result: " << result << std:: endl;
}
3.Zrem
void TestZrem ( Redis & redis)
{
redis. flushall ( ) ;
redis. zadd ( "key" , "zhangsan" , 90 ) ;
redis. zadd ( "key" , "lisi" , 91 ) ;
redis. zadd ( "key" , "wangwu" , 92 ) ;
redis. zadd ( "key" , "zhaoliu" , 93 ) ;
redis. zrem ( "key" , "zhangsan" ) ;
long long result = redis. zcard ( "key" ) ;
std:: cout << "result: " << result << std:: endl;
}
4.Zscore
void TestZscore ( Redis & redis)
{
redis. flushall ( ) ;
redis. zadd ( "key" , "zhangsan" , 90 ) ;
redis. zadd ( "key" , "lisi" , 91 ) ;
redis. zadd ( "key" , "wangwu" , 92 ) ;
redis. zadd ( "key" , "zhaoliu" , 93 ) ;
auto score = redis. zscore ( "key" , "zhangsan" ) ;
if ( score)
{
std:: cout << "score: " << score. value ( ) << std:: endl;
}
else
{
std:: cout << "score 无效" << std:: endl;
}
}