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: 等待回应

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐