ubuntu18.04安装redis
方法一 使用ubuntu官方软件库安装redis
1.获取最新的软件包
1
2sudo apt update
2.安装redis
1sudo apt install redis-server
3. 查看是否安装好并启动服务
redis-server -v //查看版本命令
ps aux | grep redis-server //查看进程命令 (redis端口号默认为 6379)
方法二 从官网上下载安装包再进行安装
1.安装tcl依赖,否则编译redis会报错
1.1进入/usr/local/tcl8.6.11
1.2下载tcl
sudo wget http://downloads.sourceforge.net/tcl/tcl8.6.11-src.tar.gz
1.3解压
sudo tar xzvf tcl8.6.1-src.tar.gz
1.4编译安装
sudo ./unix/configure
sudo make
sudo make install
2.创建redis安装目录
sudo mkdir /usr/local/redis
2.进入 /usr/local/src
2.下载安装包
sudo wget https://github.com/redis/redis/archive/7.0.5.tar.gz
3.解压安装包
tar -xzvf redis-7.0.4.tar.gz
5.进入redis-7.0.4
6.安装到/usr/local/redis
sudo make PREFIX=/usr/local/redis install
7.将配置文件redis.conf到安装目录下
cp redis.conf /usr/local/redis/bin/
安装hiredis
二、安装hiredis
C++调用redis需要配合hiredis一起使用,因此需要事先安装hiredis。
1.下载hiredis包
git clone https://github.com/redis/hiredis
2.进入hiredis文件夹
在hiredis文件夹下开启终端,并输入
make
sudo make install
(十五)使用Redis实现发布订阅功能_Last-Week的博客-CSDN博客_redisappendcommand
如何保证支持跨服务器通信
我们之前的ChatServer
是维护了一个连接的用户表,每次向别的用户发消息都会从用户表中查看对端用户是否在线。然后再判断是直接发送,还是转为离线消息。
但是现在我们是集群服务器,有多个服务器维护用户。我们的ChatServerA
要聊天的对象在ChatServerB
,ChatServerA
在自己服务器的用户表中找不到。那么可能对端用户在线,它却给对端用户发送了离线消息。因此,我们需要保证跨服务器间的通信!
那我们如何实现,非常直观的想法,我们可以让后端的服务器之间互相连接。
上面的设计,让各个ChatServer服务器互相之间直接建立TCP连接进行通信,相当于在服务器网络之间进行广播。这样的设计使得各个服务器之间耦合度太高,不利于系统扩展,并且会占用系统大量的socket资源,各服务器之间的带宽压力很大,不能够节省资源给更多的客户端提供服务,因此绝对不是一个好的设计。
集群部署的服务器之间进行通信,最好的方式就是引入中间件消息队列,解耦各个服务器,使整个系统松耦合,提高服务器的响应能力,节省服务器的带宽资源,如下图所示:
在集群分布式环境中,经常使用的中间件消息队列有ActiveMQ、RabbitMQ、Kafka等,都是应用场景广泛并且性能很好的消息队列,供集群服务器之间,分布式服务之间进行消息通信。限于我们的项目业务类型并不是非常复杂,对并发请求量也没有太高的要求,因此我们的中间件消息队列选型的是基于发布-订阅模式的redis。
Redis的安装
参考博客
Redis发布-订阅
Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息。
Redis 客户端可以订阅任意数量的频道。
下图展示了频道 channel1 , 以及订阅这个频道的三个客户端 —— client2 、 client5 和 client1 之间的关系:
当有新消息通过 PUBLISH 命令发送给频道 channel1 时, 这个消息就会被发送给订阅它的三个客户端
Redis发布-订阅代码实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36class Redis { public: Redis(); ~Redis(); //连接Redis服务器 bool connect(); //向Redis指定的通道channel发布消息 bool publish(int channel, string message); //向Redis指定的通道subscribe订阅消息 bool subscribe(int channel); //取消订阅 bool unsubscribe(int channel); //独立线程中接收订阅通道的消息 void observer_channel_message(); //初始化业务层上报通道消息的回调对象 void init_notify_handler(redis_handler handler); private: //hiredis同步上下文对象,负责publish消息 redisContext *publish_context_; //负责subscribe消息 redisContext *subcribe_context_; //回调操作,收到消息给service上报 redis_handler notify_message_handler_; };
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139#include "redis.hpp" #include <iostream> Redis::Redis() : publish_context_(nullptr), subcribe_context_(nullptr) { } Redis::~Redis() { if (publish_context_ != nullptr) { redisFree(publish_context_); } if (subcribe_context_ != nullptr) { redisFree(subcribe_context_); } } //连接Redis服务器 bool Redis::connect() { publish_context_ = redisConnect("127.0.0.1", 6379); if (publish_context_ == nullptr) { cerr << "connect redis failed!" << endl; return false; } subcribe_context_ = redisConnect("127.0.0.1", 6379); if (subcribe_context_ == nullptr) { 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) { // 相当于publish 键 值 // redis 127.0.0.1:6379> PUBLISH runoobChat "Redis PUBLISH test" redisReply *reply = (redisReply *)redisCommand(publish_context_, "PUBLISH %d %s", channel, message.c_str()); if (reply == nullptr) { cerr << "publish command failed!" << endl; return false; } // 释放资源 freeReplyObject(reply); return true; } // 向Redis指定的通道subscribe订阅消息 bool Redis::subscribe(int channel) { // redisCommand 会先把命令缓存到context中,然后调用RedisAppendCommand发送给redis // redis执行subscribe是阻塞,不会响应,不会给我们一个reply // redis 127.0.0.1:6379> SUBSCRIBE runoobChat if (REDIS_ERR == redisAppendCommand(subcribe_context_, "SUBSCRIBE %d", channel)) { cerr << "subscibe command failed" << endl; return false; } int done = 0; while (!done) { if (REDIS_ERR == redisBufferWrite(subcribe_context_, &done)) { cerr << "subscribe command failed" << endl; return false; } } return true; } //取消订阅 bool Redis::unsubscribe(int channel) { //redisCommand 会先把命令缓存到context中,然后调用RedisAppendCommand发送给redis //redis执行subscribe是阻塞,不会响应,不会给我们一个reply if (REDIS_ERR == redisAppendCommand(subcribe_context_, "UNSUBSCRIBE %d", channel)) { cerr << "subscibe command failed" << endl; return false; } int done = 0; while (!done) { if (REDIS_ERR == redisBufferWrite(subcribe_context_, &done)) { cerr << "subscribe command failed" << endl; return false; } } return true; } //独立线程中接收订阅通道的消息 void Redis::observer_channel_message() { redisReply *reply = nullptr; while (REDIS_OK == redisGetReply(subcribe_context_, (void **)&reply)) { //reply里面是返回的数据有三个,0. message , 1.通道号,2.消息 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 << "----------------------- oberver_channel_message quit--------------------------" << endl; } //初始化业务层上报通道消息的回调对象 void Redis::init_notify_handler(redis_handler handler) { notify_message_handler_ = handler; }
跨服务器通信的测试
先运行两个服务端,分别监听6000
和6002
端口。然后开启两个客户端,它们向8000
端口发起请求,这是Nginx
负责负载均衡模块的关注端口。可以看到发起的两个客户端连接分别被分派到了两个服务端,现在还需要测试跨服务端的通信是否成功。
跨服务端通信测试:
发现对端没用收到消息,后来发现终端提示redis
发布命令出错了。后来发现就没有启动redis进程!
1
2
3# 启动redis服务 redis-server redis.conf
可以看到,可以单一聊天和群组聊天。
参考
Redis进阶——发布订阅详解_·梅花十三的博客-CSDN博客_redis发布订阅模式
Redis 发布订阅 | 菜鸟教程
最后
以上就是花痴中心最近收集整理的关于C++ 实现 redis 发布订阅 --- 使用 hiredis 同步API(一)(十五)使用Redis实现发布订阅功能_Last-Week的博客-CSDN博客_redisappendcommand如何保证支持跨服务器通信Redis的安装Redis发布-订阅Redis发布-订阅代码实现跨服务器通信的测试参考的全部内容,更多相关C++内容请搜索靠谱客的其他文章。
发表评论 取消回复