程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> C基礎 redis緩存訪問,c基礎redis緩存

C基礎 redis緩存訪問,c基礎redis緩存

編輯:關於C語言

C基礎 redis緩存訪問,c基礎redis緩存


引言

  先說redis安裝, 這裡采用的環境是.  

Linux version 4.4.0-22-generic (buildd@lgw01-41) 
(gcc version 5.3.1 20160413 (Ubuntu 5.3.1-14ubuntu2) ) 
#40-Ubuntu SMP Thu May 12 22:03:46 UTC 2016

 對於 ubuntu 安裝 redis是非常簡單的. 這裡采用源碼安裝. 安裝代碼如下

wget http://download.redis.io/releases/redis-3.0.6.tar.gz
tar xzf redis-3.0.6.tar.gz
cd redis-3.0.6
make

 安裝後我的環境是

那我們測試一下. 安裝結果. 先啟動 redis-server 服務器.

再啟動 redis-cli 客戶端

我們開始測試一下. 

 測試之後一切正常. redis linux上安裝基本完畢了. 更加詳細的參照

Redis 官網教程 很詳細 http://www.redis.net.cn/tutorial/3501.html

 

前言

  現在我們安裝 redis c 訪問的驅動. hiredis. 一開始都是下載安裝. 我是直接從 hiredis git官網下載安裝的.

hiredis  源碼 https://github.com/redis/hiredis

wget https://github.com/redis/hiredis/archive/master.zip
unzip master.zip

 安裝完畢會看見這樣環境

執行安裝命令

make
sudo make install

 

本質對於 make install 執行了下面步驟

mkdir -p /usr/local/include/hiredis /usr/local/lib
cp -a hiredis.h async.h read.h sds.h adapters /usr/local/include/hiredis
cp -a libhiredis.so /usr/local/lib/libhiredis.so.0.13
cd /usr/local/lib && ln -sf libhiredis.so.0.13 libhiredis.so
cp -a libhiredis.a /usr/local/lib
mkdir -p /usr/local/lib/pkgconfig
cp -a hiredis.pc /usr/local/lib/pkgconfig

此刻基本上 hiredis 驅動已經安裝完畢. 後面解釋一下, 驅動提供的api.

常用的 api如下.

/*
 * redis鏈接函數, 返回redis上下文.
 * ip    : 鏈接地址的ip
 * port    : 鏈接端口
 *         : 返回 redis上下文, NULL表示獲取失敗
 */
redisContext *redisConnect(const char *ip, int port)


/*
 *  執行redis操作命令, 返回得到的結果集
 *    context    : redisConnect 返回的redis上下文對象
 *    format    : 等同於 printf格式控制符
 *    ...        : 後面可變參數, 需要和 format中格式符對應
 *            : 返回 得到的結果集
 */
void *redisCommand(redisContext *context, const char *format, ...);

/*
 * 釋放redis命令操作返回過來的結果集
 * reply    : redisCommand返回的結果集
 */
void freeReplyObject(void *reply);

/*
 * 釋放鏈接上下文
 * context    : redisConnect返回的鏈接上下文
 */
void redisFree(redisContext *context);

 更加詳細的解釋我們可以看 源碼接口文件 hiredis/hiredis.h .  例如

第一個是 redisConnect 返回的 redisContext上下文結構
/* Context for a connection to Redis */
typedef struct redisContext {
    int err; /* Error flags, 0 when there is no error */
    char errstr[128]; /* String representation of error when applicable */
    int fd;
    int flags;
    char *obuf; /* Write buffer */
    redisReader *reader; /* Protocol reader */
    enum redisConnectionType connection_type;
    struct timeval *timeout;
    struct {
        char *host;
        char *source_addr;
        int port;
    } tcp;
    struct {
        char *path;
    } unix_sock;
} redisContext;

還有一個是 redisCommand 返回的命令集
/* This is the reply object returned by redisCommand() */
typedef struct redisReply {
    int type; /* REDIS_REPLY_* */
    long long integer; /* The integer when type is REDIS_REPLY_INTEGER */
    int len; /* Length of string */
    char *str; /* Used for both REDIS_REPLY_ERROR and REDIS_REPLY_STRING */
    size_t elements; /* number of elements, for REDIS_REPLY_ARRAY */
    struct redisReply **element; /* elements vector for REDIS_REPLY_ARRAY */
} redisReply;

關於 hiredis基本的C驅動接口,解釋完畢. 後面開始寫demo測試一番.最好的理解方式還是看官方源碼和測試代碼.

 

正文

  首先來個簡單的demo測試. simpleget.c

#include <stdio.h>
#include <stdlib.h>
#include <hiredis/hiredis.h>

/*
 * 請求 redis網絡緩存服務器內存.
 */
int main(int argc, char* argv[]) {
    redisContext *conn = redisConnect("127.0.0.1", 6379);
    if(NULL == conn) {
        fprintf(stderr, "redisConnect 127.0.0.1:6379 error!\n");
        exit(EXIT_FAILURE);
    }   
    if(conn->err) {
        fprintf(stderr, "redisConect error:%d\n", conn->err);
        redisFree(conn);
        exit(EXIT_FAILURE);
    }   
    
    // 這裡redisConnect 鏈接對象創建完畢了
    redisReply *reply = redisCommand(conn, "get foo");
    if(reply && reply->type == REDIS_REPLY_STRING) {
        printf("get foo => %s\n", reply->str);
    }   
    printf("reply->type = %d\n", reply->type);

    // 釋放這個對象
    freeReplyObject(reply);
    // 釋放hiredis 上下文對象   
    redisFree(conn);

    return 0;
}

 

編譯命令是

gcc -Wall -ggdb -o simpleget.out simpleget.c -lhiredis

 

最終測試結果是


這裡表明流程是跑通了. 這裡擴展一下, 有時候在Linux上查找函數或宏定義聲明好麻煩. 我用的方式是

 find . -name *.h | xargs grep 'REDIS_REPLY_STRING'

 

笨方法也挺實用的. 查找的結果是 上面 REDIS_REPLY_STRING 定義在 hiredis/read.h 中 摘錄部分如下

#define REDIS_REPLY_STRING 1
#define REDIS_REPLY_ARRAY 2
#define REDIS_REPLY_INTEGER 3
#define REDIS_REPLY_NIL 4
#define REDIS_REPLY_STATUS 5
#define REDIS_REPLY_ERROR 6

 

 通過這些宏枚舉區分返回的值. 其實到這裡基本上 關於 redis接口使用基本入門了. 後面再舉一個 操作list的操作代碼 setlist.c

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <hiredis/hiredis.h>

/*
 * 請求 redis網絡緩存服務器內存.
 */
int main(int argc, char* argv[]) {
    // 忽略服務器退出,導致當前進程退出
    signal(SIGPIPE, SIG_IGN);

    redisContext *conn = redisConnect("127.0.0.1", 6379);
    if(NULL == conn) {
        fprintf(stderr, "redisConnect 127.0.0.1:6379 error!\n");
        exit(EXIT_FAILURE);
    }   
    if(conn->err) {
        fprintf(stderr, "redisConect error:%d\n", conn->err);
        redisFree(conn);
        exit(EXIT_FAILURE);
    }   
    
    // 這裡redisConnect 鏈接對象創建完畢了
    freeReplyObject(redisCommand(conn, "lpush mylist foo"));
    freeReplyObject(redisCommand(conn, "lpush mylist bar"));
    redisReply *reply = redisCommand(conn, "lrange mylist 0 -1");
    if(reply && reply->type == REDIS_REPLY_ARRAY && reply->elements == 2) {
        printf("%s %s\n", reply->element[0]->str, reply->element[1]->str);
    }   
    else {
        printf("redisCommand [lrange mylist 0 -1] error:%d. %s\n", reply->type, reply->str);
    }   

    // 釋放這個對象
    freeReplyObject(reply);
    // 釋放hiredis 上下文對象   
    redisFree(conn);

    return 0;
}

 

編譯代碼 

gcc -Wall -ggdb -o setlist.out setlist.c -lhiredis

 

 運行結果如下

更加詳細介紹請參照 hiredis git上 源碼.

 

後記

   到這裡關於C簡單使用控制redis服務器, 基本講完了. 錯誤是難免的. 歡迎指正.  

/**********************************************************************

**        直接向大師們而不是他們得的學生領悟。 

**                           —— 阿貝爾

***********************************************************************/

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved