网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
愿意放哪儿放哪儿,我觉着吧,怎么说redis也是个数据库,就放 db 文件夹下吧。
#ifndef REDIS_H
#define REDIS_H
#include <hiredis/hiredis.h>
#include
#include
using namespace std;
class Redis
{
public:
Redis();
~Redis();
// 连接redis服务器
bool connect();
// 向redis指定的通道channel发布消息
bool publish(int channel, string message);
// 向redis指定的通道subscribe订阅消息
bool subscribe(int channel);
// 向redis指定的通道unsubscribe取消订阅消息
bool unsubscribe(int channel);
// 在独立线程中接收订阅通道中的消息
void observer_channel_message();
// 初始化向业务层上报通道消息的回调对象
void init_notify_handler(function<void(int, string)> fn);
private:
// hiredis同步上下文对象,负责publish消息
redisContext *_publish_context;
// hiredis同步上下文对象,负责subscribe消息
redisContext *_subcribe_context;
// 回调操作,收到订阅的消息,给service层上报
function<void(int, string)> _notify_message_handler;
};
#endif
这一套,可以在做轻量级集群服务器间通信用,封装好了的。
#include “redis.hpp”
#include
using namespace std;
Redis::Redis():_publish_context(nullptr), _subcribe_context(nullptr){}
Redis::~Redis(){
if (_publish_context != nullptr){
redisFree(_publish_context);
}
if (_subcribe_context != nullptr){
redisFree(_subcribe_context);
}
}
bool Redis::connect(){
// 负责publish发布消息的上下文连接
_publish_context = redisConnect(“127.0.0.1”, 6379);
if (nullptr == _publish_context){
cerr << “connect redis failed!” << endl;
return false;
}
// 负责subscribe订阅消息的上下文连接
_subcribe_context = redisConnect(“127.0.0.1”, 6379);
if (nullptr == _subcribe_context){
cerr << “connect redis failed!” << endl;
return false;
}
// 在单独的线程中,监听通道上的事件,有消息给业务层进行上报
thread t(& {
observer_channel_message();
});
t.detach();
cout << “connect redis-server success!” << endl;
return true;
}
// 向redis指定的通道channel发布消息
bool Redis::publish(int channel, string message){
redisReply *reply = (redisReply *)redisCommand(_publish_context, “PUBLISH %d %s”, channel, message.c_str());
if (nullptr == reply){
cerr << “publish command failed!” << endl;
return false;
}
freeReplyObject(reply);
return true;
}
// 向redis指定的通道subscribe订阅消息
bool Redis::subscribe(int channel){
// SUBSCRIBE命令本身会造成线程阻塞等待通道里面发生消息,这里只做订阅通道,不接收通道消息
// 通道消息的接收专门在observer_channel_message函数中的独立线程中进行
// 只负责发送命令,不阻塞接收redis server响应消息,否则和notifyMsg线程抢占响应资源
if (REDIS_ERR == redisAppendCommand(this->_subcribe_context, “SUBSCRIBE %d”, channel)){
cerr << “subscribe command failed!” << endl;
return false;
}
// redisBufferWrite可以循环发送缓冲区,直到缓冲区数据发送完毕(done被置为1)
int done = 0;
while (!done){
if (REDIS_ERR == redisBufferWrite(this->_subcribe_context, &done)){
cerr << “subscribe command failed!” << endl;
return false;
}
}
// redisGetReply
return true;
}
// 向redis指定的通道unsubscribe取消订阅消息
bool Redis::unsubscribe(int channel){
if (REDIS_ERR == redisAppendCommand(this->_subcribe_context, “UNSUBSCRIBE %d”, channel)){
cerr << “unsubscribe command failed!” << endl;
return false;
}
// redisBufferWrite可以循环发送缓冲区,直到缓冲区数据发送完毕(done被置为1)
int done = 0;
while (!done){
if (REDIS_ERR == redisBufferWrite(this->_subcribe_context, &done)){
cerr << “unsubscribe command failed!” << endl;
return false;
}
}
return true;
}
// 在独立线程中接收订阅通道中的消息
void Redis::observer_channel_message(){
redisReply *reply = nullptr;
while (REDIS_OK == redisGetReply(this->_subcribe_context, (void **)&reply)){
// 订阅收到的消息是一个带三元素的数组
if (reply != nullptr && reply->element[2] != nullptr && reply->element[2]->str != nullptr)
{
// 给业务层上报通道上发生的消息
_notify_message_handler(atoi(reply->element[1]->str) , reply->element[2]->str);
}
freeReplyObject(reply);
}
cerr << “>>>>>>>>>>>>> observer_channel_message quit <<<<<<<<<<<<<” << endl;
}
void Redis::init_notify_handler(function<void(int,string)> fn){
this->_notify_message_handler = fn;
}
头文件里面自行修改吧,这里放出源文件的修改范围。
构造函数中连接上redis:
// 连接redis服务器
if (_redis.connect()){
// 设置上报消息的回调
_redis.init_notify_handler(std::bind(&ChatService::handleRedisSubscribeMessage, this, _1, _2));
}
登录成功后,向redis消息队列进行订阅:
// id用户登录成功后,向redis订阅channel(id)
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
);
}
登录成功后,向redis消息队列进行订阅:
// id用户登录成功后,向redis订阅channel(id)
[外链图片转存中…(img-E0qo71k6-1715523949564)]
[外链图片转存中…(img-dHnCvKVg-1715523949564)]
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!