直接上代码:该代码在循环中反复执行可能会导致死锁,解决的办法见后文
#include
#include
#include "TestRedis.h"
using namespace std;
#ifdef _WIN32
#include
#endif /* _WIN32 */
#pragma comment( lib, "ws2_32.lib")//最好的方法是包含在项目属性中,因为那样可以根据Debug、Release、x86、x64来区分。这里仅仅是为了突出引用了这个库写在这里
bool StartWSA(void)
{
//! Windows netword DLL init
WORD version = MAKEWORD(2, 2);
WSADATA data;
if (WSAStartup(version, &data) != 0)
{
std::cerr << "WSAStartup() failure" << std::endl;
return false;
}
return true;
}
void StopWSA(void)
{
WSACleanup();
}
typedef std::function reply_callback_t;
void fun_call_back(cpp_redis::reply& _reply)
{
std::cout << _reply << endl;
}
void cpp_redis_connect(cpp_redis::redis_client& _client)
{
//! Enable logging
cpp_redis::active_logger = std::unique_ptr(new cpp_redis::logger);
_client.connect("127.0.0.1", 6379, [](cpp_redis::redis_client&)
{
std::cout << "client disconnected (disconnection handler)" << std::endl;
});
}
int main(void)
{
//启动Windows网络通信库
if (!StartWSA())
{
return -1;
}
try
{
cpp_redis::redis_client client;
cpp_redis_connect(client);
//hash 增删改查
//新增:批量
vector> vecPair = { { "key1", "value1" },{ "key2", "value2" },{ "key3", "value3" } };
client.hmset("MyHashSet", vecPair, [](cpp_redis::reply& _reply) {
std::cout<<"新增批量:key1 key2 key3. " << _reply << endl;
});
//新增:单个
client.hset("MyHashSet", "key4", "value4", [](cpp_redis::reply& _reply) {
std::cout << "新增单个:key4. " << _reply << endl;
});
//查询:批量
client.hgetall("MyHashSet", [](cpp_redis::reply& _reply)//这种查询适合批量返回结果的情形,避免了来回的网络传输
{
std::cout << "查询批量:MyHashSet" << endl;
for each (auto& var in _reply.as_array())//这种方式返回的key 和value是挨着放的,因为是getall,所以不存在nill的情况(只要返回的vector的size>0)
{
std::cout << var << endl;
}
});
//修改:单个
client.hset("MyHashSet", "key4", "VALUE4", [](cpp_redis::reply& _reply) {
std::cout << "修改单个:MyHashSet key4 VALUE4. " << _reply << endl;
});
//查询:单个
client.hget("MyHashSet", "key4", [](cpp_redis::reply& _reply)
{
std::cout << "查询单个:MyHashSet key4. " << _reply << endl;
});
//删除:批量
vector vecKeys = { "key1", "key2", "key_not_exist" };//删除不存在的key不会有任何影响,对客户端来说
client.hdel("MyHashSet", vecKeys, [](cpp_redis::reply& _reply) {
std::cout << "删除:批量:MyHashSet : key1, key2, key_not_exist. " << _reply << endl;
});
//查询:批量
client.hgetall("MyHashSet", [](cpp_redis::reply& _reply)//这种查询适合批量返回结果的情形,避免了来回的网络传输
{
std::cout << "查询:批量:MyHashSet :" <0)
{
std::cout << var << endl;
}
});
// synchronous commit 同步提交:将上面的所有get set 等方法依次执行完, no timeout
client.sync_commit();
}
catch (cpp_redis::redis_error e)
{
std::cout << e.what() << endl;
}
//关闭Windows网络通信库
StopWSA();
return 0;
}
输出结果:符合预期
上面的代码封装成test_fun_redis_hash()的话,下面的代码会死锁:
int main(int argc, char* argv[])
{
//启动Windows网络通信库
if (!StartWSA())
{
return -1;
}
while (true)
{
test_use_cpp_redis_with_rapidjson();
Sleep(10);
}
//关闭Windows网络通信库
StopWSA();
return 0;
}
主要原因是:
1 cpp_redis采用延迟执行的方式,get set 都是把数据追加到client的成员buffer里,等commit的时候一起执行。
2 当连续执行多个get的时候,可以最后一次性commit
3 当连续执行多个set的时候,可以最后一次性commit
4 当多个get/set针对同一个redis库中的对象交叉执行时(可能会造成死锁),避免死锁的办法就是每次get/set之后就提交一次commit
上文问题解决办法:
1 在每一个get/set之后都commit一次(连续多个get可以用一个commit,连续多个set也可以用一个commit)
修改后不会死锁的代码如下:
#include
#include
#include "TestRedis.h"
using namespace std;
#ifdef _WIN32
#include
#endif /* _WIN32 */
#pragma comment( lib, "ws2_32.lib")//最好的方法是包含在项目属性中,因为那样可以根据Debug、Release、x86、x64来区分。这里仅仅是为了突出引用了这个库写在这里
bool StartWSA(void)
{
//! Windows netword DLL init
WORD version = MAKEWORD(2, 2);
WSADATA data;
if (WSAStartup(version, &data) != 0)
{
std::cerr << "WSAStartup() failure" << std::endl;
return false;
}
return true;
}
void StopWSA(void)
{
WSACleanup();
}
typedef std::function reply_callback_t;
void fun_call_back(cpp_redis::reply& _reply)
{
std::cout << _reply << endl;
}
void cpp_redis_connect(cpp_redis::redis_client& _client)
{
//! Enable logging
cpp_redis::active_logger = std::unique_ptr(new cpp_redis::logger);
_client.connect("127.0.0.1", 6379, [](cpp_redis::redis_client&)
{
std::cout << "client disconnected (disconnection handler)" << std::endl;
});
}
void test_use_cpp_redis_with_rapidjson(void)
{
try
{
cpp_redis::redis_client client;
cpp_redis_connect(client);
string val;
//hash 增删改查
//新增:批量
vector> vecPair = { { "key1", "value1" },{ "key2", "value2" },{ "key3", "value3" } };
client.hmset("MyHashSet", vecPair, [&](cpp_redis::reply& _reply) {
std::cout << "新增批量:key1 key2 key3. " << _reply << endl;
});
client.sync_commit();
//新增:单个
client.hset("MyHashSet", "key4", "value4", [&](cpp_redis::reply& _reply) {
std::cout << "新增单个:key4. " << _reply << endl;
});
client.sync_commit();
//查询:批量
client.hgetall("MyHashSet", [&](cpp_redis::reply& _reply)//这种查询适合批量返回结果的情形,避免了来回的网络传输
{
std::cout << "查询批量:MyHashSet" << endl;
for each (auto& var in _reply.as_array())//这种方式返回的key 和value是挨着放的,因为是getall,所以不存在nill的情况(只要返回的vector的size>0)
{
std::cout << var.as_string() << endl;
}
});
client.sync_commit();
//修改:单个
client.hset("MyHashSet", "key4", "VALUE4", [&](cpp_redis::reply& _reply) {
std::cout << "修改单个:MyHashSet key4 VALUE4. " << _reply << endl;
});
client.sync_commit();
//查询:单个
client.hget("MyHashSet", "key4", [&](cpp_redis::reply& _reply)
{
std::cout << "查询单个:MyHashSet key4. " << _reply.as_string() << endl;
val = _reply.as_string();
cout << "val:" << val << endl;
});
client.sync_commit();
//删除:批量
vector vecKeys = { "key1", "key2", "key_not_exist" };//删除不存在的key不会有任何影响,对客户端来说
client.hdel("MyHashSet", vecKeys, [&](cpp_redis::reply& _reply) {
std::cout << "删除:批量:MyHashSet : key1, key2, key_not_exist. " << _reply << endl;
});
client.sync_commit();
//查询:批量
client.hgetall("MyHashSet", [&](cpp_redis::reply& _reply)//这种查询适合批量返回结果的情形,避免了来回的网络传输
{
std::cout << "查询:批量:MyHashSet :" << endl;
for each (auto& var in _reply.as_array())//这种方式返回的key 和value是挨着放的,因为是getall,所以不存在nill的情况(只要返回的vector的size>0)
{
std::cout << var.as_string() << endl;
}
});
// synchronous commit 同步提交:将上面的所有get set 等方法依次执行完, no timeout
client.sync_commit();
}
catch (cpp_redis::redis_error e)
{
std::cout << e.what() << endl;
}
}
int main(void)
{
//启动Windows网络通信库
if (!StartWSA())
{
return -1;
}
while (true)
{
test_use_cpp_redis_with_rapidjson();
Sleep(10);
}
//关闭Windows网络通信库
StopWSA();
return 0;
}