1.redis簡介
Redis是一個開源(BSD許可),內存存儲的數據結構服務器,可用作數據庫,高速緩存和消息隊列代理。它支持字符串、哈希表、列表、集合、有序集合,位圖,hyperloglogs等數據類型。內置複製、Lua腳本、LRU收回、事務以及不同級別磁盤持久化功能,同時通過Redis Sentinel提供高可用,通過Redis Cluster提供自動分區。
注:redis可跨平臺,可運行於windows和linux各版本,作者平臺ubuntu14.04,下載版本爲linux,有興趣讀者可搜索windows上使用方法。
2.redis源碼下載及安裝
2.1.源碼下載
源碼下載地址:選取官網
官網上亦有大量相關介紹,欲進一步學習瞭解,可參閱官網內容。
注:爲配合源碼分析,作者下載的爲redis 3.0版本,下載位置一樣。
2.2.安裝方法
Redis的代碼遵循ANSI-C編寫,可以在所有POSIX系統(如Linux, *BSD, Mac OS X, Solaris等)上安裝運行。而且Redis並不依賴任何非標準庫,也沒有編譯參數必需添加。redis的安裝出奇的簡單,這可能也是他風靡的一個原因,讓人很容易上手,不像某些東西,編譯階段就能讓人完全絕望。
1)解壓:
tar –zxvf redis-2.4.6.tar.gz
編譯
需要說明的事,redis的安裝非常簡單,已經有現成的Makefile文件,直接運行make命令即可。
make
make install
注意安裝權限問題。
2)安裝成功與否測試
終端運行:redis-server,就可以啓用redis服務,可以用netstat命令查看redis監聽的端口(默認是6379)
或調用:ps -aux |grep redis 查看進程
另開啓終端,運行:redis-cli
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> set test hello
OK
127.0.0.1:6379> get test
"hello"
127.0.0.1:6379>
3.redis配置
redis-server /etc/path<redis>/redis.conf
注意:修改redis路徑。
作者直接選取其默認配置,未做修改,該部分後續根據需要進行補充,有需要的讀者可參考網上相關文章,亦可參考其官網說明文檔,很詳細。
4.redis使用實例
4.1.redis命令操作
參考redis官網教程。
4.2.linux下C語言調用--hiredis
4.2.1.C語言接口庫下載
Redis 是一個高性能的key-value數據庫。 redis的出現,很大程度補償了memcached這類key/value存儲的不足,在部 分場合可以對關係數據庫起到很好的補充作用。它提供了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang等客戶端,使用很方便。
在這裏簡單介紹一下redis的C接口庫:C語言接口函數庫hiredis,下載地址:https://github.com/redis/hiredis
hiredis是redis的C接口庫,使用之前我們要先下載安裝hiredis,下載地址:https://github.com/redis/hiredis.git
git clone https://github.com/redis/hiredis.git
下載之後進入hiredis目錄
make
make install
4.2.2.hiredis簡介
下面進行hredis庫中幾個常用函數介紹
(1)redisConnect函數
該函數用於連接redis數據庫
函數原型:
1 redisContext *redisConnect(const char *ip, int port); 2 //說明:該函數用來連接redis數據庫,參數爲數據庫的ip地址和端口,一般redis數據庫的端口爲6379該函數返回一個結構體redisContext。
redisContext結構體定義如下:
1 /* Context for a connection to Redis */ 2 typedef struct redisContext { 3 int err; /* Error flags, 0 when there is no error */ 4 char errstr[128]; /* String representation of error when applicable */ 5 int fd; 6 int flags; 7 char *obuf; /* Write buffer */ 8 redisReader *reader; /* Protocol reader */ 9 10 enum redisConnectionType connection_type; 11 struct timeval *timeout; 12 13 struct { 14 char *host; 15 char *source_addr; 16 int port; 17 } tcp; 18 19 struct { 20 char *path; 21 } unix_sock; 22 23 } redisContext;
(2)redisCommand函數
該函數用於執行redis的命令;
函數原型:
1 void *redisCommand(redisContext *c, const char *format, ...); 2 /*說明:該函數執行命令,就如sql數據庫中的SQL語句一樣,只是執行的是redis數據庫中的操作命令, 3 第一個參數爲連接數據庫時返回的redisContext, 4 後面爲可變參數列表,跟C語言printf函數類似, 5 返回值爲void*,一般強制轉換成爲redisReply類型的進行進一步的處理。*/
用法:
redisReply *reply = (redisReply*)redisCommand(c, cmd);
redisReply結構體定義如下:
1 /* This is the reply object returned by redisCommand() */ 2 typedef struct redisReply { 3 int type; /* REDIS_REPLY_* */ 4 long long integer; /* The integer when type is REDIS_REPLY_INTEGER */ 5 size_t len; /* Length of string */ 6 char *str; /* Used for both REDIS_REPLY_ERROR and REDIS_REPLY_STRING */ 7 size_t elements; /* number of elements, for REDIS_REPLY_ARRAY */ 8 struct redisReply **element; /* elements vector for REDIS_REPLY_ARRAY */ 9 } redisReply;
下面是幾種redis的常見錯誤及返回值類型
1 #define REDIS_ERR -1 2 #define REDIS_OK 0 3 #define REDIS_ERR_IO 1 /* Error in read or write */ 4 #define REDIS_ERR_EOF 3 /* End of file */ 5 #define REDIS_ERR_PROTOCOL 4 /* Protocol error */ 6 #define REDIS_ERR_OOM 5 /* Out of memory */ 7 #define REDIS_ERR_OTHER 2 /* Everything else... */ 8 9 #define REDIS_REPLY_STRING 1 //返回字符串,查看str,len字段 10 #define REDIS_REPLY_ARRAY 2 //返回一個數組,查看elements的值(數組個數),通過element[index]的方式訪問數組元素,每個數組元素是一個redisReply對象的指針 11 #define REDIS_REPLY_INTEGER 3 //返回整數,從integer字段獲取值 12 #define REDIS_REPLY_NIL 4 //沒有數據返回 13 #define REDIS_REPLY_STATUS 5 //表示狀態,內容通過str字段查看,字符串長度是len字段 14 #define REDIS_REPLY_ERROR 6 //表示出錯,查看出錯信息,如上的str,len字段
(3)redisRelpyObject函數
還函數用於釋放redisCommand返回值redisReply所佔用的內存
1 /* Free a reply object */ 2 void freeReplyObject(void *reply) 3 //該函數用於回收釋放redisCommand返回值redisReply所佔用的內存
(4)redisFree函數
該函數用於釋放一個redis數據庫的連接
1 void redisFree(redisContext *c) 2 //用於釋放redisConnect產生的連接
4.2.3.使用示例
下面寫一個簡單的hredis c接口的redis測試程序:
1 #include <stdio.h> 2 #include <string.h> 3 #include <stddef.h> 4 #include <stdarg.h> 5 #include <string.h> 6 #include <assert.h> 7 #include <hiredis/hiredis.h> //redis C接口庫 8 9 #define REDIS_HOST "127.0.0.1" 10 #define REDIS_PORT 6379 11 12 redisContext *g_ctx = NULL; 13 14 int redis_init() 15 { 16 redisContext *c = NULL; 17 c = redisConnect(REDIS_HOST, REDIS_PORT); 18 if (NULL == c || c->err) { 19 if(c) { 20 printf("Redis [%s:%d], Error:[%s]\n", REDIS_HOST, REDIS_PORT, c->errstr); 21 redisFree(c); 22 } else { 23 printf("Redis [%s:%d] failure\n", REDIS_HOST, REDIS_PORT); 24 } 25 return -1; 26 } 27 g_ctx = c; 28 29 return 0; 30 } 31 32 void redis_free() 33 { 34 if (g_ctx) { 35 redisFree(g_ctx); 36 } 37 g_ctx = NULL; 38 } 39 40 int redis_test(const char *cmd) 41 { 42 int i = 0; 43 redisReply *r = NULL; 44 if (NULL == cmd) { 45 return -1; 46 } 47 48 printf("%s\n", cmd); 49 50 r = (redisReply *)redisCommand(g_ctx, cmd); 51 if (NULL == r) { 52 printf("%s, Error[%d:%s]", g_ctx->err, g_ctx->errstr); 53 return -1; 54 } 55 56 printf("type: %d\n", r->type); 57 switch(r->type) { 58 case REDIS_REPLY_STATUS: 59 printf("type:%s, reply->len:%d reply->str:%s\n", "REDIS_REPLY_STATUS", r->len, r->str); 60 break; 61 case REDIS_REPLY_ERROR: 62 printf("type:%s, reply->len:%d reply->str:%s\n", "REDIS_REPLY_ERROR", r->len, r->str); 63 break; 64 case REDIS_REPLY_INTEGER: 65 printf("type:%s, reply->integer:%lld\n", "REDIS_REPLY_INTEGER", r->integer); 66 break; 67 case REDIS_REPLY_NIL: 68 printf("type:%s, no data\n", "REDIS_REPLY_NIL"); 69 break; 70 case REDIS_REPLY_STRING: 71 printf("type:%s, reply->len:%d reply->str:%s\n", "REDIS_REPLY_STRING", r->len, r->str); 72 break; 73 case REDIS_REPLY_ARRAY: 74 printf("type:%s, reply->elements:%d\n", "REDIS_REPLY_ARRAY", r->elements); 75 for (i = 0; i < r->elements; i++) { 76 printf("%d: %s\n", i, r->element[i]->str); 77 } 78 break; 79 default: 80 printf("unkonwn type:%s\n", r->type); 81 break; 82 } 83 84 /*release reply and context */ 85 freeReplyObject(r); 86 return 0; 87 } 88 89 int main() 90 { 91 const char *cmd = NULL; 92 93 /* init redis */ 94 if (redis_init()) { 95 return -1; 96 } 97 98 /* 1: SET<--->GET */ 99 printf("SET<--->GET\n"); 100 cmd = "set foo bar"; 101 redis_test(cmd); 102 cmd = "get foo"; 103 redis_test(cmd); 104 105 /* 2: SADD<--->SMEMBERS */ 106 printf("\nSADD<--->SMEMBERS\n"); 107 cmd = "SADD namelist jack lily lucy tom"; 108 redis_test(cmd); 109 cmd = "SMEMBERS namelist"; 110 redis_test(cmd); 111 112 /* 3: .....*/ 113 114 /* free redis context */ 115 redis_free(); 116 117 return 0; 118 }
運行結果:
SET<--->GET set foo bar type: 5 type:REDIS_REPLY_STATUS, reply->len:2 reply->str:OK get foo type: 1 type:REDIS_REPLY_STRING, reply->len:3 reply->str:bar SADD<--->SMEMBERS SADD namelist jack lily lucy tom type: 3 type:REDIS_REPLY_INTEGER, reply->integer:0 SMEMBERS namelist type: 2 type:REDIS_REPLY_ARRAY, reply->elements:4 0: lucy 1: jack 2: lily 3: tom