1.redis环境安装和配置
sudo apt-get install redis-server # ubuntu命令安装redis服务
ps -ef | grep redis
ubuntu通过上面命令安装完redis,会自动启动redis服务,通过ps命令确认,可以看到redis默认工作在本地主机的6379端口上。
2.Redis发布订阅
2.1.redis数据库的命令
1.订阅频道的命令是 subscribe
redis的发布-订阅机制:发布-订阅模式包含了两种角色,分别是消息的发布者和消息的订阅者。订阅者可以订阅一个或者多个频道channel,发布者可以向指定的频道channel发送消息,所有订阅此频道的订阅者都会收到此消息。
订阅频道的命令是 subscribe,可以同时订阅多个频道,用法是 subscribe channel1 [channel2
...],
SUBSCRIBE "zhang san"
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "zhang san"
3) (integer) 1
# <=========== 此处订阅了"zhang san"这个频道,进入订阅阻塞状态,等待该频道上的信息
执行上面命令客户端会进入订阅状态,处于此状态下客户端不能使用除subscribe、unsubscribe、
psubscribe和punsubscribe这四个属于"发布/订阅"之外的命令,否则会报错。
注意:订阅是阻塞等待的
2.给频道发布消息 publish
publish "zhang san" "hello world!"
(integer) 1
3.c++操作Redis
redis支持多种不同的客户端编程语言,例如Java对应jedis、php对应phpredis、C++对应的则是hiredis。
怎么安装看我下面这个博客
c++操作redis数据库(详解)_@seven@的博客-CSDN博客_c++访问redis
3.1代码
// 向redis指定的通道channel发布消息
// 向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订阅消息 // 向redis指定的通道unsubscribe取消订阅消息
// 向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;
}
4.代码讲解
一个redis对象里面含有两个hiredis同步上下文对象,负责publish消息,负责subscribe消息。subscribe会阻塞一个上下文。向redis指定的通道unsubscribe取消订阅消息,不然消息队列里面数据只增不减。
// 订阅收到的消息是一个带三元素的数组:message + 通道号+消息
C++使用hiredis客户端进行subscribe 和publish,unsubscribe编程, Redis模块是封装好的,业务只需要调用对象提供的api接口。然后里面的具体实现,业务不需要关心。而里面是怎么实现的,其实和我们使用数据库进行crud本质是一样的,组装好redis数据库语言,根据redis提供给c++的api接口发送过去就可以了。不过注意的是,subscribe命令是阻塞等待的,这里封装的subscribe和redis里面的不一样。只有下面两个,redisGetReply,需要redis对象里面会多开一个线程去处理,专门等待接收数据,其实就是执行redisGetReply命令。如何接收到数据怎么处理,就是由我们注册的回调函数决定了。
subscribe命令本质:
redisAppendCommand :将命令放到本地缓存
redisBufferWrite :将命令从本地缓存放到数据库缓存里面
redisGetReply: 等待回应