1. hiredis
这时redis自带的官方的C语言API。安装很简单:
# cd {redis-src}
# cd deps/hiredis/
# make
# make install
现在hiredis已经被安装于/usr/local/include/hiredis/和/usr/local/lib/下。为了方便,设置一下头文件和lib文件的路径:
# vim ~/.bashrc
#compile time, paths to search included headers, referenced libs;
export C_INCLUDE_PATH=.:/usr/local/include/hiredis:$C_INCLUDE_PATH
export CPLUS_INCLUDE_PATH=.:/usr/local/include/hiredis:$CPLUS_INCLUDE_PATH
export LIBRARY_PATH=.:/usr/local/lib:$LIBRARY_PATH
#runtime, paths to search referenced libs;
export LD_LIBRARY_PATH=.:/usr/local/lib:$LD_LIBRARY_PATH
然后,就可以基于hiredis API开发客户端了。可是hiredis不支持集群。支持集群的API:
C++ https://github.com/eyjian/r3cC++ https://github.com/zhengshuxin/acl
C https://github.com/vipshop/hiredis-vip.git
hiredis-vip是基于hiredis的(事实上,它包含一个完整的hiredis),在hiredis的基础上,提供了一套cluster版本的接口。
安装: 由于hiredis-vip包含了完整的hiredis,在安装hiredis-vip之前,先卸载前面安装的hiredis。# rm -fr /usr/local/include/hiredis/
# rm -f /usr/local/lib/libhiredis.*
# wget https://github.com/vipshop/hiredis-vip/archive/master.zip
# unzip master.zip
# cd hiredis-vip-master/
# make
# vim Makefile (更改INSTALL_LIBRARY_PATH,免得受系统环境变量LIBRARY_PATH影响);
INSTALL_LIBRARY_PATH=/usr/local/lib/hiredis-vip
# make install
现在,头文件安装于/usr/local/include/hiredis-vip目录,包含hiredis.h,hircluster.h等;lib文件安装于/usr/local/lib/hiredis-vip目录,主要是libhiredis_vip.so;为了方便,设置一下头文件和lib文件的路径:
# vim ~/.bashrc
#compile time, paths to search included headers, referenced libs;
export C_INCLUDE_PATH=.:/usr/local/include/hiredis-vip:$C_INCLUDE_PATH
export CPLUS_INCLUDE_PATH=.:/usr/local/include/hiredis-vip:$CPLUS_INCLUDE_PATH
export LIBRARY_PATH=.:/usr/local/lib/hiredis-vip:$LIBRARY_PATH
#runtime, paths to search referenced libs;
export LD_LIBRARY_PATH=.:/usr/local/lib/hiredis-vip:$LD_LIBRARY_PATH
2.1 hiredis-vip sync API
#include<stdio.h>
#include<hircluster.h>
int main()
{
redisClusterContext *cc = redisClusterConnect("127.0.0.1:7000,127.0.0.1:7001",HIRCLUSTER_FLAG_NULL);
if(cc == NULL || cc->err)
{
printf("connect error : %s\n", cc == NULL ? "NULL" : cc->errstr);
return -1;
}
int i;
redisReply* reply = NULL;
for(i=0; i<10000; i++)
{
//set
reply = redisClusterCommand(cc, "set key%d value%d", i, i);
if(reply == NULL)
{
printf("set key%d, reply is NULL, error info: %s\n", i, cc->errstr);
redisClusterFree(cc);
return -1;
}
printf("set key%d, reply:%s\n", i, reply->str);
freeReplyObject(reply);
//get
reply = redisClusterCommand(cc, "get key%d", i);
if(reply == NULL)
{
printf("get key%d, reply is NULL, error info: %s\n", i, cc->errstr);
redisClusterFree(cc);
return -1;
}
printf("get key%d, reply:%s\n", i, reply->str);
freeReplyObject(reply);
}
redisClusterFree(cc);
return 0;
}
编译运行:
<pre name="code" class="plain"># gcc -lhiredis_vip sync.c
# ./a.out
......
set key9998, reply:OK
get key9998, reply:value9998
set key9999, reply:OK
get key9999, reply:value9999
2.2 hiredis-vipi async API
#include<stdio.h>
#include<hircluster.h>
#include<adapters/libevent.h>
int all_count=0;
void getCallback(redisClusterAsyncContext *acc, void *r, void *privdata)
{
redisReply *reply = r;
int count = *(int*)privdata;
all_count ++;
if(all_count >= count)
{
redisClusterAsyncDisconnect(acc);
}
}
void connectCallback(const redisAsyncContext *c, int status)
{
if (status != REDIS_OK) {
printf("Error: %s\n", c->errstr);
return;
}
printf("Connected...\n");
}
void disconnectCallback(const redisAsyncContext *c, int status)
{
if (status != REDIS_OK) {
printf("Error: %s\n", c->errstr);
return;
}
printf("\nDisconnected...\n");
}
int main(int argc, char **argv)
{
int status;
struct event_base *base = event_base_new();
redisClusterAsyncContext *acc = redisClusterAsyncConnect("127.0.0.1:7001,127.0.0.1:7001",HIRCLUSTER_FLAG_NULL);
if (acc->err)
{
printf("Error: %s\n", acc->errstr);
return 1;
}
redisClusterLibeventAttach(acc,base);
redisClusterAsyncSetConnectCallback(acc,connectCallback);
redisClusterAsyncSetDisconnectCallback(acc,disconnectCallback);
int count = 10000;
int i;
for(i = 0; i < 10000; i ++)
{
status = redisClusterAsyncCommand(acc, getCallback, &count, "set %d %d", i, i);
if(status != REDIS_OK)
{
printf("error: %d %s\n", acc->err, acc->errstr);
}
}
event_base_dispatch(base);
return 0;
}
# gcc -lhiredis_vip -levent async.c
# ./a.out
Connected...
Connected...
Connected...
Disconnected...
Disconnected...
Disconnected...