xRedis是我开源的一个redis 的c++ client,主要是对redis官方的hiredis库的C++封装。
对redis提供的命令基于简单易用方面的考虑,封装为C++接口,并提供了连接池,数据多节点分片存储,
主从节点读写分离等功能,也简单封装了一个支持REDIS CLUTSTER的客户端。
目前有以下的功能和特点:
- 支持数据多节点分布存储,可自定义分片规则;
- 支持同时连接到每个分片的主从节点,支持主从读写分离;
- 支持对每个存储节点建立连接池;
- 支持同时连接多个数据分片集群;
- 提供简单易用的C++接口封装,已实现大部分REDIS命令;
- 只依赖hiredis库;
- 多线程安全
项目的源码地址: https://github.com/0xsky/xredis
源码安装:
git clone https://github.com/0xsky/xredis
cd xredis
make
sudo make install
xRedisClient架构图解:
xRedis集群节点配置
xRedisClient做为与redis服务器间的连接管理器,支持同时连接多组不同配置的REDIS存储集群。
举例来说明的话,有组redis存储集群groupA、groupB,A集群配置为支持三个存储节点,B集群配置支持5个REDIS存储节点。
配置表如下:
RedisNode RedisList1[3]=
{
{0,"127.0.0.1", 7000, "", 2, 5, 0},
{1,"127.0.0.1", 7000, "", 2, 5, 0},
{2,"127.0.0.1", 7000, "", 2, 5, 0}
};
RedisNode RedisList2[5]=
{
{0,"127.0.0.1", 7000, "", 2, 5, 0},
{1,"127.0.0.1", 7000, "", 2, 5, 0},
{2,"127.0.0.1", 7000, "", 2, 5, 0},
{3,"127.0.0.1", 7000, "", 2, 5, 0},
{4,"127.0.0.1", 7000, "", 2, 5, 0},
};
先初始化。
xRedisClient xRedis;
xRedis.Init(CACHE_TYPE_MAX);
根据配置信息,连接到不同的存储集群:
xRedis.ConnectRedisCache(RedisList1, 3, CACHE_TYPE_1);
xRedis.ConnectRedisCache(RedisList2, 5, CACHE_TYPE_2);
以上的配置信息表,这里的每个配置节点项,本质上只是一个虚拟的节点,每个集群可以配置为支持多个虚拟节点,
但实际上可以为相同的物理节点,也可以是不同的物理节点,配置表里的节点数,实际上是支持的最大物理节点数。
在连接到Redis服务器时,会按配置里的连接池数,对每个存节点建立连接池。
xRedis的分布式核心结构 RedisDBIdx
访问redis服务器时,需要指定当访问的是哪个存储集群,并且需要指定当前存储集群的分布算法。
这些都是在RedisDBIdx 类里实现的,RedisDBIdx 自带了两种数据分布实现:
bool CreateDBIndex(const char *key, HASHFUN fun, unsigned int type);
这个方法里面实现的是,对输入的key 使用 哈希函数fun 运算后,再对存储基数取模,就得到了key所存储的节点索引。
bool CreateDBIndex(int64_t id, unsigned int type);
这个方法里实现的是对传入的UID,直接取mod,得到此uid所对应的存储节点索引,使用这种方式存储的好处是,同一个用户
(uid)的数据是存储在同一个REDIS节点里的。
对比上面的两种存储时的分片规则,各有优点,使用需要根据实际场景特点进行选择。
操作REDIS数据的代码如下:
const char *key = "test";
const char *value = "test value";
RedisDBIdx dbi(&xRedis);
bool bRet = dbi.CreateDBIndex(key, APHash, CACHE_TYPE_1);
if (!bRet) {
return 0;
}
bool bRet = xRedis.set(dbi, key, value)) \
if (bRet){
printf("success \r\n");
} else {
printf("error [%s] \r\n", dbi.GetErrInfo());
}
有的时候,上面的方式并不能满足我们的实际需要,那怎么办呢? 其实,RedisDBIdx 类的本质只是表示
key所在的节点的索引,某个KEY存储在哪个节点上,我们完全可以自己定。只要自己继承下RedisDBIdx 类,
实现自己想要的HASH算法就可以了。
bool RedisDBIdx::CreateDBIndex(const char *key, HASHFUN fun, const unsigned int type) {
unsigned int hashbase = mClient->GetRedisPool()->getHashBase(type);
if ((NULL!=fun) && (hashbase>0)) {
mIndex = fun(key)%hashbase;
mType = type;
return true;
}
return false;
bool RedisDBIdx::CreateDBIndex(const int64_t id, const unsigned int type) {
unsigned int hashbase = mClient->GetRedisPool()->getHashBase(type);
if (hashbase>0) {
mType = type;
mIndex = id%hashbase;
return true;
}
return false;
xRedis使用过程中的问题说明:
1. xRedis是线程安全的吗?还是我需要自己做一些线程锁?
多线程下,在不同的线程访问同一个xredisclient对像,不需要加锁,内部有锁处理。
2. xRedis支持windows么,怎么在windows下使用?
支持。有关在win下使用的问题,在这里总结一下: xredis依赖hiredis,因此需先要先在win
下编译hiredis库, hiredis在win下编译使用,可以看下微软的:https://github.com/MSOpenTech/redis 编译好win下的hiredis后,就可以直接在C++里使用xredis了。
3.redis连接超时后断开,有没有相应的自动重连机制呢?
比如redis的连接,由于长时间不通讯,这时候会被redis服务器断开,这时候我需要手动重新启动xredis还是可以设置什么方式保持连接?
xrdis提供keepalive方法,需要使用者自己按需要定时调用,检测连接异常,keepalive内部检测连接异常时会尝试重连接。
4.xRedisClient支持redis cluster么?
xRedisClient主要是一个redis的client,内部实现了基于数据分片的多节点存储,是不同于redis官方的集群实现。
不能直接访问redis cluster的。不过,为了方便C++访问redis cluster的需要,xredis单独封装了一个支持访问redis cluster的
xRedisClusterClient类,https://github.com/0xsky/xredis/blob/master/src/xRedisClusterClient.h
具体的使用方法请看demo示例。