redis,總想着像Mysql同樣,在C/C++中進行對接。因而查詢了一些資料,最後找到了hiredis。然而直接用它的話,不免有點不方便。因而,對其進行封裝。ios
hiredis直接去git上克隆,地址:https://github.com/redis/hiredis。git
下載好以後,因爲其自帶Makefile,只要make一下就編譯出靜態庫與動態庫了,接着把頭文件和靜/動態庫放在相應的文件夾裏就能夠了。注意若是使用動態庫,並且是放在/usr/local/lib/裏,得執行ldconfig命令,來更新一下配置,或者得配置一下動態庫路徑。github
安裝好了就是如何使用的事了。面試
學習hiredis主要是參考這兩個連接:redis
http://blog.csdn.net/gqtcgq/article/details/51344232sql
http://blog.csdn.net/achelloworld/article/details/41598389?utm_source=tuicool&utm_medium=referraljson
文章給你們分享C/C++,Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒體,CDN,P2P,K8S,Docker,TCP/IP,協程,DPDK技術,面試技巧方面的資料分享的https://ke.qq.com/course/417774?flowToken=1011069函數
一共就五個函數。學習
一、redisContext* redisConnect(const char *ip, int port)二、redisContext* redisConnectWithTimeout(const char *ip, int port, timeval tv)三、void redisFree(redisContext *c)四、void *redisCommand(redisContext *c, const char *format...)五、void freeReplyObject(void *reply) 測試
和Mysql同樣,要對接,第一件事就是用IP和端口號創建鏈接什麼的。redis的端口號通常是6379,IP直接用127.0.0.1就能夠了。既然要用到IP和端口號,又是可能會變的東西,爲了避免使想要改變它們的時候得直接修改代碼,我寫了個配置文件:
redisConf.json
1 {
2 "IP" : "127.0.0.1" ,
3 "PORT" : 6379
4 }
相應地,有提取配置信息的類
redisConf.h
1 #ifndef __REDISCONF_H__
2 #define __REDISCONF_H__
3 #include <string>
4 namespace ccx{
5 using std::string;
6 class RedisConf
7 {
8 public:
9 RedisConf();
10 void getConf();
11 string getIP();
12 int getPort();
13 private:
14 string _ip;
15 int _port;
16 };
17 }
18 #endif
redisconf.cc
1 #include "redisConf.h"
2 #include <stdlib.h>
3 #include <json/json.h>
4 #include <string>
5 #include <iostream>
6 #include <fstream>
7
8 namespace ccx{
9
10 using std::ifstream;
11 using std::cout;
12 using std::endl;
13
14 RedisConf::RedisConf()
15 {
16 getConf();
17 }
18
19 void RedisConf::getConf()
20 {
21 ifstream ifs;
22 ifs.open("redisConf.json");
23 if(!ifs.good())
24 {
25 cout << "open RedisConf.json error" << endl;
26 exit(EXIT_FAILURE);
27 }
28
29 Json::Value root;
30 Json::Reader reader;
31 if(!reader.parse(ifs, root, false))
32 {
33 cout << "RedisConf json reader error" << endl;
34 exit(EXIT_FAILURE);
35 }
36
37 _ip = root["IP"].asString();
38 _port = root["PORT"].asInt();
39 ifs.close();
40 }
41
42 string RedisConf::getIP()
43 {
44 return _ip;
45 }
46
47 int RedisConf::getPort()
48 {
49 return _port;
50 }
51
52 }
而後是目前的redis類:
redis.h
1 #ifndef __REDIS_H__
2 #define __REDIS_H__
3
4 #include "redisConf.h"
5
6 #include <hiredis/hiredis.h>
7
8
9 namespace ccx{
10
11 class Redis
12 {
13 public:
14 Redis();
15 public:
16 void Connect();
17 void disConnect();
18 public:
19 void setString(const string & key, const string & value);
20 void setString(const string & key, const int & value);
21 void setString(const string & key, const float & value);
22 private:
23 void setString(const string & data);
24 public:
25 void getString(const string & key, string & value);
26 void getString(const string & key, int & value);
27 void getString(const string & key, float & value);
28 private:
29 void getString(const string & key);
30 private:
31 void freeReply();
32 bool isError();
33 private:
34 RedisConf _conf;
35 redisContext * _context;
36 redisReply * _reply;
37 };
38 }
39
40 #endif下面結合寫好的代碼說說前面的五個函數。
函數1是用來鏈接redis的,具體以下:1 void Redis::Connect()
2 {
3 _context = ::redisConnect(_conf.getIP().c_str(), _conf.getPort());
4 cout << _conf.getIP() << "-" << _conf.getPort() << endl;
5 if(_context && _context->err)
6 {
7 cout << "connect redis error" << endl;
8 exit(EXIT_FAILURE);
9 }
10 cout << "redis Connect success" << endl;
11 }
函數2是在1的基礎上,添加了一個超時功能。
函數3是在不使用redis了,要斷開鏈接時使用的:
1 void Redis::disConnect()
2 {
3 ::redisFree(_context);
4 cout << "redis disConnect success" << endl;
5 }
函數4稍微複雜一些,有點像C中的printf:
1 printf("%d%s%d",d1,s1,d2);
2 printf("hello,world");
能夠這樣用:
1 char * command = "SET name lili";
2 reply = (redisReply*)::redisCommand(context, command);
3 char * s1 = "name";
4 char * s2 = "lili";
5 reply = (redisReply*)::redisCommand(context, "SET %s %s", s1, s2);
6 reply = (redisReply*)::redisCommand(context, "SET name lili");
7 ...
第一個參數context是函數1或者2的返回值,告訴它要與哪裏的redis進行交互。reply指向命令結果的存儲位置。
函數5是用來清理函數4 的返回結果的:
1 void Redis::freeReply()
2 {
3 if(_reply)
4 {
5 ::freeReplyObject(_reply);
6 _reply = NULL;
7 }
8 }
第6行是由於對這個函數不熟,就乾脆清完以後給它賦值NULL。
因爲redis的string中存的多是字符串、整形、浮點數,因而各自重載了三個版本的get與set方法,並重用一些函數,以減小代碼量。
對於set,直接用一個宏替換:
1 #define SETSTRING(key, value) \
2 stringstream ss;\
3 ss << "SET " << key << " " << value;\
4 string s;\
5 getline(ss, s);\
6 setString(s);
1 void Redis::setString(const string & key, const string & value)
2 {
3 SETSTRING(key, value);
4 }
5 void Redis::setString(const string & key, const int & value)
6 {
7 SETSTRING(key, value);
8 }
9 void Redis::setString(const string & key, const float & value)
10 {
11 SETSTRING(key, value);
12 }
使用C++中的stringstream,會比用「%d」、「%s」、「%f」來區分類型少些代碼。兩種方法的結果是相同的。
它們共用的setString方法:
1 void Redis::setString(const string & data)
2 {
3 freeReply();
4 _reply = (redisReply*)::redisCommand(_context, data.c_str());
5 if(!isError())
6 {
7 if (!(_reply->type == REDIS_REPLY_STATUS && strcasecmp(_reply->str,"OK") == 0))
8 {
9 cout << "Failed to execute SET(string)" << endl;
10 }
11 }
12 }
這裏的isError是用來判斷是否鏈接異常的:
1 bool Redis::isError()
2 {
3 if(NULL == _reply)
4 {
5 freeReply();
6 disConnect();
7 Connect();
8 return true;
9 }
10 return false;
11 }
若是鏈接異常,得斷開重連。
在redis命令行裏,若是set成功,會提示「OK」。因而,這裏先判斷了一下命令結果的數據類型,若是是字符串,再判斷它是否是「OK」,以此來判斷set是否成功。
對於get,我試了各類方法,都沒法直接從命令結果中提取出數字,暫時還沒找到緣由。可是數字卻能夠以字符串格式獲得。因而,使用了atoi來處理:
1 void Redis::getString(const string & key)
2 {
3 freeReply();
4 _reply = (redisReply*)::redisCommand(_context, "GET %s", key.c_str());
5 }
6
7 void Redis::getString(const string & key, string & value)
8 {
9 getString(key);
10 if(!isError() && _reply->type == REDIS_REPLY_STRING)
11 {
12 value = _reply->str;
13 }
14 }
15
16 void Redis::getString(const string & key, int & value)
17 {
18 getString(key);
19 if(!isError() && _reply->type == REDIS_REPLY_STRING)
20 {
21 value = ::atoi(_reply->str);
22 }
23 }
24
25 void Redis::getString(const string & key, float & value)
26 {
27 getString(key);
28 if(!isError() && _reply->type == REDIS_REPLY_STRING)
29 {
30 value = ::atof(_reply->str);
31 }
32 }
redis.cc
View Code
test.cc
View Code
測試結果以下:
127.0.0.1-6379
redis Connect success
lii
30
30
redis disConnect success