0.hiredis的使用

Hiredis是一個Redis的C客戶端庫函數(shù),基本實現(xiàn)了Redis的協(xié)議的最小集。這里對hiredis的api作基本的介紹以及應(yīng)用,主要參考hiredis的README文件以及相關(guān)源碼。

  1. hiredis的安裝,這個就不贅述了懦趋,很簡單。

  2. 同步API接口的使用

我們的項目中使用的hireds接口都是同步的API疹味,所謂同步意思就是使用阻塞的方式向redis server下發(fā)消息仅叫。

接口的主要部分為下面三個部分,下面分別介紹糙捺。

/**連接數(shù)據(jù)庫*/
redisContext *redisConnect(const char *ip, int port);
/**發(fā)送命令請求*/
void *redisCommand(redisContext *c, const char *format, ...);
void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);
void redisAppendCommand(redisContext *c, const char *format, ...);
void redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);
/*釋放資源*/
void freeReplyObject(void *reply);
void redisFree(redisContext *c);

2.1連接redis數(shù)據(jù)庫
2.1.1函數(shù)原型:

redisContext *redisConnect(const char *ip, int port);

2.1.2參數(shù)說明:
port:為redis數(shù)據(jù)監(jiān)聽的端口號诫咱,redis默認監(jiān)聽的端口號為6379
ip:為redis數(shù)據(jù)庫的IP地址,可以是遠程的洪灯,也可以是本地的127.0.0.1

2.1.3返回值
返回值是一個指向redisContext對象遂跟,可以不用了解這個對象的具體組成部分,只需要知道怎么使用就可以了婴渡。下面是其定義幻锁。

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;

2.1.4 使用例子

redisContext *c = redisConnect("127.0.0.1", 6379);
if (c == NULL || c->err) {
    if (c) {
        printf("Error: %s\n", c->errstr);
        // handle error
    } else {
        printf("Can't allocate redis context\n");
    }
}

這個redisContext不是一個線程安全的對象,也就是說边臼,多個線程同時訪問這一個對象可能會出現(xiàn)問題哄尔。

2.2 發(fā)送需要執(zhí)行的命令
2.2.1發(fā)送命令函數(shù)原型

void *redisCommand(redisContext *c, const char *format, ...);

2.2.2參數(shù)說明
這個函數(shù)是一個帶有不定參數(shù)的∧ⅲ可以按著format格式給出對應(yīng)的參數(shù)岭接,這就和printf函數(shù)類似富拗。
c 是一個reidsConnect函數(shù)返回的一個對象。

2.2.3返回值
返回值是一個void類型的指針鸣戴,實際為指向一個redisReply類型的指針啃沪。
redisReply的定義

/* This is the reply object returned by redisCommand() */
typedef struct redisReply {
    /*命令執(zhí)行結(jié)果的返回類型*/
    int type; /* REDIS_REPLY_* */
    /*存儲執(zhí)行結(jié)果返回為整數(shù)*/
    long long integer; /* The integer when type is REDIS_REPLY_INTEGER */
    /*字符串值的長度*/
    size_t len; /* Length of string */
    /*存儲命令執(zhí)行結(jié)果返回是字符串*/
    char *str; /* Used for both REDIS_REPLY_ERROR and REDIS_REPLY_STRING */
    /*返回結(jié)果是數(shù)組的大小*/
    size_t elements; /* number of elements, for REDIS_REPLY_ARRAY */
    /*存儲執(zhí)行結(jié)果返回是數(shù)組*/
    struct redisReply **element; /* elements vector for REDIS_REPLY_ARRAY */
} redisReply;

返回結(jié)果的類型reply->type,reply 為redisReply* 類型。
REDIS_REPLY_STRING == 1:返回值是字符串,字符串儲存在redis->str當中,字符串長度為redis->len窄锅。
REDIS_REPLY_ARRAY == 2:返回值是數(shù)組创千,數(shù)組大小存在redis->elements里面,數(shù)組值存儲在redis->element[i]里面入偷。數(shù)組里面存儲的是指向redisReply的指針追驴,數(shù)組里面的返回值可以通過redis->element[i]->str來訪問,數(shù)組的結(jié)果里全是type==REDIS_REPLY_STRING的redisReply對象指針疏之。
REDIS_REPLY_INTEGER == 3:返回值為整數(shù) long long殿雪。
REDIS_REPLY_NIL==4:返回值為空表示執(zhí)行結(jié)果為空。
REDIS_REPLY_STATUS ==5:返回命令執(zhí)行的狀態(tài)锋爪,比如set foo bar 返回的狀態(tài)為OK丙曙,存儲在str當中 reply->str == "OK"。
REDIS_REPLY_ERROR ==6 :命令執(zhí)行錯誤,錯誤信息存放在 reply->str當中其骄。

redisCommandArgv函數(shù)
函數(shù)原型

void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);

參數(shù)說明
argvlen這個數(shù)組存儲了命令參數(shù)中亏镰,每一個參數(shù)的長度,包含命令本身年栓,比如 set foo bar 則argvlen ={3,3,3},如果argvlen為空,那么這個函數(shù)內(nèi)部會自動調(diào)用strlen函數(shù)對每個參數(shù)進行求長度薄霜。
argv 存放每個命令參數(shù)的指針某抓,argv={"set","foo","bar"}
argc 存放命令參數(shù)的個數(shù)上面的例子中argc=3
c 為redisContext對象。
為每一個參數(shù)指定長度惰瓜,可以是二進制安全的函數(shù)否副。函數(shù)會按著長度來決定字符串的終止,而不是'\0'.

char hkey[] = "123456";
char hset[] = "hset";
char key[] = "testkey";
char hvalue[] = "3210";
int argc = 4;
char *argv[] = {hset,key,hkey,hvalue};
size_t argvlen[] = {4,6,4,3};
redisCommandArgv(context,argc,argv,argvlen);

hgetall testkey
會得到321并不會得到和hvalue一樣的值"3210"崎坊,因為在hset命令中指定了長度备禀,只會讀取前面的三個字符。

redisAppendCommand*函數(shù)支持管道命令
函數(shù)原型:

void redisAppendCommand(redisContext *c, const char *format, ...);
void redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);
int redisGetReply(redisContext *context,redisReply** reply);

參數(shù)說明:
redisAppendCommand函數(shù)和redisCommand函數(shù)參數(shù)一致奈揍,format可以指定特定參數(shù)的類型曲尸。
c 為redisContext對象
redisAppendCommandArgv函數(shù)和redisCommandArgv函數(shù)類似,參數(shù)含義也相同男翰。
redisGetReply函數(shù)用來獲得執(zhí)行的結(jié)果的一條返回另患,并存儲在reply所指的對象當中。成功返回REDIS_OK,否則返回REIDS_ERR蛾绎。多條命令的一次性返回結(jié)果都存放在redisContext里面昆箕。
所不同的是鸦列,這個兩個命令的結(jié)果。這兩個函數(shù)是把多個命令存放在緩沖區(qū)內(nèi)鹏倘,然后一起發(fā)送給redis服務(wù)器薯嗤,一次執(zhí)行∠吮茫可以通過redisGetReply函數(shù)從
redisContext中取出返回的結(jié)果骆姐。

使用例子:

redisReply *reply;
/*添加命令set */
redisAppendCommand(context,"SET foo bar");
/*添加命令get */
redisAppendCommand(context,"GET foo");
/*獲取set命令結(jié)果*/
redisGetReply(context,&reply); // reply for SET
freeReplyObject(reply);
/*獲取get命令結(jié)果*/
redisGetReply(context,&reply); // reply for GET
freeReplyObject(reply);

2.3 釋放資源
2.3.1函數(shù)原型

void freeReplyObject(void *reply);
void redisFree(redisContext *c);

2.3.2參數(shù)說明
freeReplyObject函數(shù)中reply 實際為指向redisReply結(jié)構(gòu)體的指針,可能是redisCommand的返回值夕吻,后續(xù)可以看到以也能是管道命令執(zhí)行結(jié)果的返回值诲锹。
redisFree函數(shù)中c實際為指向redisContext對象,這個函數(shù)會清理連接資源并釋放連接涉馅。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末归园,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子稚矿,更是在濱河造成了極大的恐慌庸诱,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,607評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件晤揣,死亡現(xiàn)場離奇詭異桥爽,居然都是意外死亡,警方通過查閱死者的電腦和手機昧识,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評論 3 395
  • 文/潘曉璐 我一進店門钠四,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人跪楞,你說我怎么就攤上這事缀去。” “怎么了甸祭?”我有些...
    開封第一講書人閱讀 164,960評論 0 355
  • 文/不壞的土叔 我叫張陵缕碎,是天一觀的道長。 經(jīng)常有香客問我池户,道長咏雌,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,750評論 1 294
  • 正文 為了忘掉前任校焦,我火速辦了婚禮赊抖,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘寨典。我一直安慰自己熏迹,他們只是感情好,可當我...
    茶點故事閱讀 67,764評論 6 392
  • 文/花漫 我一把揭開白布凝赛。 她就那樣靜靜地躺著注暗,像睡著了一般坛缕。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上捆昏,一...
    開封第一講書人閱讀 51,604評論 1 305
  • 那天赚楚,我揣著相機與錄音,去河邊找鬼骗卜。 笑死宠页,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的寇仓。 我是一名探鬼主播举户,決...
    沈念sama閱讀 40,347評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼遍烦!你這毒婦竟也來了俭嘁?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,253評論 0 276
  • 序言:老撾萬榮一對情侶失蹤服猪,失蹤者是張志新(化名)和其女友劉穎供填,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體罢猪,經(jīng)...
    沈念sama閱讀 45,702評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡近她,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,893評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了膳帕。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片粘捎。...
    茶點故事閱讀 40,015評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖危彩,靈堂內(nèi)的尸體忽然破棺而出攒磨,到底是詐尸還是另有隱情,我是刑警寧澤恬砂,帶...
    沈念sama閱讀 35,734評論 5 346
  • 正文 年R本政府宣布咧纠,位于F島的核電站蓬痒,受9級特大地震影響泻骤,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜梧奢,卻給世界環(huán)境...
    茶點故事閱讀 41,352評論 3 330
  • 文/蒙蒙 一狱掂、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧亲轨,春花似錦趋惨、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽讯嫂。三九已至,卻和暖如春兆沙,著一層夾襖步出監(jiān)牢的瞬間欧芽,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評論 1 270
  • 我被黑心中介騙來泰國打工葛圃, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留千扔,地道東北人。 一個月前我還...
    沈念sama閱讀 48,216評論 3 371
  • 正文 我出身青樓库正,卻偏偏與公主長得像曲楚,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子褥符,可洞房花燭夜當晚...
    茶點故事閱讀 44,969評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 官網(wǎng) 中文版本 好的網(wǎng)站 Content-type: text/htmlBASH Section: User ...
    不排版閱讀 4,383評論 0 5
  • 《男盜女娼》 在這個男盜女娼的世界龙誊,總有人叫囂著自己就是真流氓,而不愿意承認自己就是偽君子属瓣。 《陌路》 原來相愛的...
    何鯨洛閱讀 183評論 0 1
  • 是什么讓我鼓起勇氣重新讀一遍孫子兵法载迄,暫且不細說,究竟是什么能讓我有此膽量將這手字流露出來抡蛙,不得而知哈哈护昧,第一...
    Amber0128閱讀 655評論 0 0
  • 最近看了一本神奇的書,《秘密》粗截。里面介紹了一個玄而又玄的理論:吸引力法則惋耙。你頭腦中所想的事情、場景熊昌,總能被吸...
    言小海閱讀 859評論 0 4