├── .gitignore
├── .travis.yml
├── .vscode
└── settings.json
├── LICENSE
├── README-cn.md
├── README.md
├── doc
├── xRedis编译安装.md
├── xredis_0.png
├── 使用xRedis连接官方集群.md
└── 使用xRedis连接自定义数据分片集群.md
├── examples
├── Makefile
├── cluster-cli.cpp
├── demo.cpp
├── demo_multi_slice.cpp
├── demo_slice.cpp
├── redis-cluster-client.cpp
├── xRedisClusterClient_test.cpp
├── xredis-example-Consistent-hash
│ ├── CMd5.cpp
│ ├── CMd5.h
│ ├── redis-test.cpp
│ └── xredis-example-Consistent-hash.cpp
└── xredis-example.cpp
├── makefile
├── src
├── xLock.h
├── xRedisClient.cpp
├── xRedisClient.h
├── xRedisClient_connection.cpp
├── xRedisClient_hashs.cpp
├── xRedisClient_keys.cpp
├── xRedisClient_lists.cpp
├── xRedisClient_pubsub.cpp
├── xRedisClient_sets.cpp
├── xRedisClient_sortedsets.cpp
├── xRedisClient_strings.cpp
├── xRedisClusterClient.cpp
├── xRedisClusterClient.h
├── xRedisClusterManager.h
├── xRedisLog.cpp
├── xRedisLog.h
├── xRedisPool.cpp
└── xRedisPool.h
└── test
└── xredis-test.cpp
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled Object files
2 | *.slo
3 | *.lo
4 | *.o
5 | *.obj
6 |
7 | # Compiled Dynamic libraries
8 | *.so
9 | *.dylib
10 | *.dll
11 |
12 | # Compiled Static libraries
13 | *.lai
14 | *.la
15 | *.a
16 | *.lib
17 |
18 | # Executables
19 | *.exe
20 | *.out
21 | *.app
22 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false # 开启基于容器的Travis CI任务,让编译效率更高。
2 | language: cpp
3 | os:
4 | - linux
5 |
6 | compiler:
7 | - gcc
8 |
9 | branches:
10 | only:
11 | - master
12 |
13 | env:
14 | matrix:
15 | - REDIS=1
16 | global:
17 | - CURPATH=$(pwd)
18 | - TOOLSDIR=$HOME/Tools
19 | - HIREDISDIR=$TOOLSDIR/redis
20 | - LD_LIBRARY_PATH=$HIREDISDIR:$LD_LIBRARY_PATH
21 | - COMPILER=g++-7
22 |
23 | before_install:
24 | - mkdir -p $TOOLSDIR
25 | - cd $TOOLSDIR
26 | - wget http://download.redis.io/releases/redis-3.0.6.tar.gz
27 | - tar zxf redis-3.0.6.tar.gz
28 |
29 | before_script:
30 | - export
31 |
32 | - cd redis-3.0.6/deps/hiredis
33 | - make
34 | - sudo make install
35 |
36 | script:
37 | - export
38 | - cd $TRAVIS_BUILD_DIR
39 | - make
40 |
41 | - sudo make install
42 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "C_Cpp.clang_format_fallbackStyle": "WebKit"
3 | }
--------------------------------------------------------------------------------
/README-cn.md:
--------------------------------------------------------------------------------
1 | xRedis
2 | ======
3 |
4 | xRedis 是一个C++开发的redis客户端,是对hiredis的C++封装,提供易用的redis命令操作接口.
5 |
6 | ***功能与特点:***
7 | * 支持数据多节点分布存储,可自定义分片规则;
8 | * 支持同时连接到每个分片的主从节点,支持主从读写分离;
9 | * 支持对每个存储节点建立连接池;
10 | * 支持同时连接多个数据分片集群;
11 | * 支持连接到官方集群,支持单个节点和多个节点
12 | 建立到每个节点的连接池,client端自动计算slot分布。
13 | 支持自动计算节点索引位置,支持REDIS集群节点变化连接自动切换;
14 | 当官方集群节点有添加/删除/slot分布变化时,到集群的连接池会自动更新。
15 | * 提供简单易用的C++接口封装,已实现大部分REDIS命令;
16 | * 只依赖hiredis库;
17 | * 多线程安全
18 | * 支持带密码连接;
19 | * 支持linux、windows平台
20 |
21 |
22 | ### Dependencies
23 |
24 | xredis 依赖 hiredis , 在使用xRedis前需要安装[hiredis](https://github.com/redis/hiredis/)库
25 |
26 | ### Install
27 |
28 | 第一步 安装libhiredis
29 | 在Debian系统上:
30 | ```bash
31 | sudo apt-get install libhiredis-dev
32 | ```
33 |
34 | xRedis源码安装
35 | ```bash
36 | git clone https://github.com/0xsky/xredis
37 | cd xredis
38 | make
39 | sudo make install
40 | ```
41 | 使用说明
42 | ```C++
43 | #使用 xRedisClusterClient类 访问 redis节点或是官方集群(redis cluster)
44 |
45 | #include "xRedisClusterClient.h"
46 | int main(int argc, char **argv) {
47 | xRedisClusterClient redisclient;
48 | # 连接到REDIS,建立大小为4的连接池,
49 | # 若此节点是官方集群的成员,则会自动对集群每个主节点建立大小为4的连接池。
50 | std::string passwd = "passwd123";
51 | bool bRet = redisclient.connect("127.0.0.1", 6379, passwd, 4);
52 |
53 | RedisResult result;
54 | redisclient.command(result, "set %s %s", "key", "hello");
55 |
56 | printf("type:%d integer:%lld str:%s \r\n",
57 | result.type(), result.integer(), result.str());
58 |
59 | while (true) {
60 | usleep(1000*1000*6);
61 | // 定时调用 keepalive 检测断线重连接,以及集群状态变化。
62 | redisclient.keepalive();
63 | }
64 |
65 | return 0;
66 | }
67 | ```
68 |
69 | 更多使用示例
70 | 使用示例 [examples]目录(https://github.com/0xsky/xredis/blob/master/examples)
71 |
72 | demo.cpp 使用xredisclient访问单个redis节点示例
73 | demo_slice.cpp 使用xredisclient访问单组多分片(节点)redis分片集群示例
74 | demo_multi_slice.cpp 使用xredisclient访问多组多分片(节点)redis分片集群示例
75 | xredis-example.cpp 使用xredisclient 批量操作示例
76 | xredis-example-Consistent-hash xredisclient使用一致性hash,自定义数据分片存储demo
77 |
78 | xRedisClusterClient_test.cpp 使用xRedisClusterClient实现简单的redis官方集群客户端示例
79 | cluster-cli.cpp 使用 xRedisClusterClient 实现的连接redis集群的client,支持集群节增加/删除、slot分布变化时,自动切换。
80 |
81 | /test/xredis-test.cpp 多个redis命令的使用示例
82 |
83 | ### 相关文档
84 |
85 |
86 | ### 计划
87 | 添加 Redis 哨兵模式支持
88 |
89 |
90 | ##### xRedis 分片存储架构图
91 | 
92 |
93 | [xRedis API](http://xredis.0xsky.com/)
94 | 使用示例 [examples](https://github.com/0xsky/xredis/blob/master/examples) directory for some examples
95 | xRedis开源社区QQ群: 190107312
96 |
97 | 作者: xSky
98 | 博客: [xSky's Blog](https://0xsky.com/)
99 | xRedis QQ 群: 190107312
100 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | xRedis
2 | [](https://travis-ci.org/freeeyes/PSS)
3 | [](https://opensource.org/licenses/Apache-2.0 )
4 | [](https://badge.fury.io/gh/0xsky%2Fxredis)
5 | ======
6 |
7 | C++ Redis client, support the data slice storage, redis cluster, connection pool, read/write separation.
8 |
9 | **Features:**
10 | * Support multi-node distributed storage of data, can customize the sharding rules;
11 | * Support to connect to master and slave nodes of each shard at the same time, support separation of master and slave reads and writes;
12 | * Support connection pooling for each storage node;
13 | * Support simultaneous connection of multiple data sharding clusters;
14 | * Support for connecting to official clusters, single or multiple nodes
15 | Support to set up a connection pool to each node, the client side automatically calculates the slot distribution.
16 | Support automatic calculation of node index position, support Redis cluster node change connection automatic switch;
17 | The connection pool to the cluster is automatically updated when the add/delete /slot distribution of the official cluster node changes.
18 | * Provide easy to use C++ interface encapsulation, has implemented most of the Redis command;
19 | * Only rely on the Hiredis library;
20 | * Multi-thread safety
21 | * Support password connection;
22 | * Support Linux and Windows platforms
23 |
24 | 中文版说明文档[点这里](https://github.com/0xsky/xredis/blob/master/README-cn.md)
25 |
26 | ### Dependencies
27 |
28 | xredis requires hiredis only
29 |
30 | ### Install
31 |
32 | First step install libhiredis, on a Debian system you can use:
33 |
34 | ```bash
35 | sudo apt-get install libhiredis-dev
36 | ```
37 |
38 | on centos/redhat/fedora system you can use:
39 | ```bash
40 | sudo yum install hiredis-devel
41 | ```
42 |
43 | Then checkout the code and compile it
44 | ```bash
45 | git clone https://github.com/0xsky/xredis
46 | cd xredis
47 | make
48 | sudo make install
49 | ```
50 |
51 | Usage
52 | ```C++
53 | #Accessing redis or redis Cluster using the xRedisClusterClient class
54 |
55 | #include "xRedisClusterClient.h"
56 | int main(int argc, char **argv) {
57 | xRedisClusterClient redisclient;
58 | # Connect to REDIS and establish a connection pool
59 | # If this node is a member of the REDIS cluster,
60 | # a connection pool is automatically established for each primary node in the cluster.
61 | std::string passwd = "passwd123";
62 | bool bRet = redisclient.connect("127.0.0.1", 6379, passwd, 4);
63 |
64 | RedisResult result;
65 | redisclient.command(result, "set %s %s", "key", "hello");
66 |
67 | printf("type:%d integer:%lld str:%s \r\n",
68 | result.type(), result.integer(), result.str());
69 |
70 | while (true) {
71 | usleep(1000*1000*6);
72 | redisclient.keepalive();
73 | }
74 |
75 | return 0;
76 | }
77 | ```
78 | ### Todo
79 | Support redis sentinel
80 |
81 | ### Documentation
82 | 
83 |
84 | [xRedis API Site](http://xredis.0xsky.com/)
85 | See [examples](https://github.com/0xsky/xredis/blob/master/examples) directory for some examples
86 |
87 | blog: [xSky's Blog](https://0xsky.com/)
88 | xRedis QQ Group: 190107312
89 |
90 |
--------------------------------------------------------------------------------
/doc/xRedis编译安装.md:
--------------------------------------------------------------------------------
1 | xRedis
2 | ======
3 |
4 | xRedis 是一个C++开发的redis客户端,是对hiredis的C++封装,提供易用的redis命令操作接口.
5 |
6 | ***功能与特点:***
7 | * 支持数据多节点分布存储,可自定义分片规则;
8 | * 支持同时连接到每个分片的主从节点,支持主从读写分离;
9 | * 支持对每个存储节点建立连接池;
10 | * 支持同时连接多个数据分片集群;
11 | * 支持连接到官方集群,支持单个节点和多个节点
12 | 建立到每个节点的连接池,client端自动计算slot分布。
13 | 支持自动计算节点索引位置,支持REDIS集群节点变化连接自动切换;
14 | 当官方集群节点有添加/删除/slot分布变化时,到集群的连接池会自动更新。
15 | * 提供简单易用的C++接口封装,已实现大部分REDIS命令;
16 | * 只依赖hiredis库;
17 | * 多线程安全
18 | * 支持带密码连接;
19 | * 支持linux、windows平台
20 |
21 |
22 | ### Dependencies
23 |
24 | xredis 依赖 hiredis , 在使用xRedis前需要安装[hiredis](https://github.com/redis/hiredis/)库
25 |
26 | ### Install
27 |
28 | 第一步 安装libhiredis
29 | 在Debian系统上:
30 | ```bash
31 | sudo apt-get install libhiredis-dev
32 | ```
33 |
34 | xRedis源码安装
35 | ```bash
36 | git clone https://github.com/0xsky/xredis
37 | cd xredis
38 | make
39 | sudo make install
40 | ```
41 | 使用说明
42 | ```C++
43 | #使用 xRedisClusterClient类 访问 redis节点或是官方集群(redis cluster)
44 |
45 | #include "xRedisClusterClient.h"
46 | int main(int argc, char **argv) {
47 | xRedisClusterClient redisclient;
48 | # 连接到REDIS,建立大小为4的连接池,
49 | # 若此节点是官方集群的成员,则会自动对集群每个主节点建立大小为4的连接池。
50 | std::string passwd = "passwd123";
51 | bool bRet = redisclient.connect("127.0.0.1", 6379, passwd, 4);
52 |
53 | RedisResult result;
54 | redisclient.command(result, "set %s %s", "key", "hello");
55 |
56 | printf("type:%d integer:%lld str:%s \r\n",
57 | result.type(), result.integer(), result.str());
58 |
59 | while (true) {
60 | usleep(1000*1000*6);
61 | // 定时调用 keepalive 检测断线重连接,以及集群状态变化。
62 | redisclient.keepalive();
63 | }
64 |
65 | return 0;
66 | }
67 | ```
68 |
69 | 更多使用示例
70 | 使用示例 [examples]目录(https://github.com/0xsky/xredis/blob/master/examples)
71 |
72 | demo.cpp 使用xredisclient访问单个redis节点示例
73 | demo_slice.cpp 使用xredisclient访问单组多分片(节点)redis分片集群示例
74 | demo_multi_slice.cpp 使用xredisclient访问多组多分片(节点)redis分片集群示例
75 | xredis-example.cpp 使用xredisclient 批量操作示例
76 | xredis-example-Consistent-hash xredisclient使用一致性hash,自定义数据分片存储demo
77 |
78 | xRedisClusterClient_test.cpp 使用xRedisClusterClient实现简单的redis官方集群客户端示例
79 | cluster-cli.cpp 使用 xRedisClusterClient 实现的连接redis集群的client,支持集群节增加/删除、slot分布变化时,自动切换。
80 |
81 | /test/xredis-test.cpp 多个redis命令的使用示例
82 |
83 |
--------------------------------------------------------------------------------
/doc/xredis_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xsky/xredis/39c20a584c62cfa24895fd444f63d1e22ddff8e7/doc/xredis_0.png
--------------------------------------------------------------------------------
/doc/使用xRedis连接官方集群.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xsky/xredis/39c20a584c62cfa24895fd444f63d1e22ddff8e7/doc/使用xRedis连接官方集群.md
--------------------------------------------------------------------------------
/doc/使用xRedis连接自定义数据分片集群.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xsky/xredis/39c20a584c62cfa24895fd444f63d1e22ddff8e7/doc/使用xRedis连接自定义数据分片集群.md
--------------------------------------------------------------------------------
/examples/Makefile:
--------------------------------------------------------------------------------
1 |
2 | LIBS=-L../ -I../src -lhiredis -lpthread
3 | all: demo demo_slice demo_multi_slice xredis-example xRedisClusterClient_test
4 |
5 | demo:
6 | g++ ${LIBS} demo.cpp -o demo
7 | demo_slice:
8 | g++ ${LIBS} demo_slice.cpp -o demo_slice
9 | demo_multi_slice:
10 | g++ ${LIBS} demo_multi_slice.cpp -o demo_multi_slice
11 | xredis-example:
12 | g++ ${LIBS} xredis-example.cpp -o xredis-example
13 | xRedisClusterClient_test:
14 | g++ ${LIBS} -I/usr/local/include/hiredis xRedisClusterClient_test.cpp -o xRedisClusterClient_test
15 |
16 | clean:
17 | rm -f demo
18 | rm -f demo_slice
19 | rm -f demo_multi_slice
20 | rm -f xredis-example
21 | rm -f xRedisClusterClient_test
22 | rm -f cluster-cli
23 |
24 |
--------------------------------------------------------------------------------
/examples/cluster-cli.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * ----------------------------------------------------------------------------
3 | * Copyright (c) 2013-2021, xSky
4 | * All rights reserved.
5 | * Distributed under GPL license.
6 | * ----------------------------------------------------------------------------
7 | */
8 |
9 | /** \example cluster-cli.cpp
10 | * This is an example used by XredisClusterClient
11 | * Implemented a simple Redis console client
12 | * Connecting a single Redis node and an official Redis cluster is supported
13 | */
14 |
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 |
22 | #include
23 |
24 | using std::cin;
25 | using std::cout;
26 | using std::endl;
27 |
28 | #include "xRedisClusterClient.h"
29 | using namespace xrc;
30 |
31 | xRedisClusterClient* redis = NULL;
32 |
33 | static int str2Vect(const char* pSrc, std::vector& vDest, const char* pSep = ",")
34 | {
35 | if (NULL == pSrc) {
36 | return -1;
37 | }
38 |
39 | int iLen = strlen(pSrc);
40 | if (iLen == 0) {
41 | return -1;
42 | }
43 |
44 | char* pTmp = new char[iLen + 1];
45 | if (pTmp == NULL) {
46 | return -1;
47 | }
48 |
49 | memcpy(pTmp, pSrc, iLen);
50 | pTmp[iLen] = '\0';
51 |
52 | char* pCurr = strtok(pTmp, pSep);
53 | while (pCurr) {
54 | vDest.push_back(pCurr);
55 | pCurr = strtok(NULL, pSep);
56 | }
57 |
58 | delete[] pTmp;
59 | return 0;
60 | }
61 |
62 | void timer_handle(int sig)
63 | {
64 | (void)sig;
65 |
66 | redis->keepalive();
67 | }
68 |
69 | void init_timer()
70 | {
71 | struct sigevent evp;
72 | struct itimerspec ts;
73 | timer_t timer;
74 |
75 | memset(&evp, 0, sizeof(struct sigevent));
76 | evp.sigev_value.sival_ptr = &timer;
77 | evp.sigev_notify = SIGEV_SIGNAL;
78 | evp.sigev_signo = SIGUSR1;
79 | signal(SIGUSR1, timer_handle);
80 |
81 | int ret = timer_create(CLOCK_REALTIME, &evp, &timer);
82 | if (ret) {
83 | perror("timer_create");
84 | return;
85 | }
86 |
87 | ts.it_interval.tv_sec = 5;
88 | ts.it_interval.tv_nsec = 0;
89 | ts.it_value.tv_sec = 5;
90 | ts.it_value.tv_nsec = 0;
91 |
92 | ret = timer_settime(timer, 0, &ts, NULL);
93 | if (ret)
94 | perror("timer_settime");
95 | }
96 |
97 | void log_demo(int level, const char* line)
98 | {
99 | printf("xRedis %u %s", level, line);
100 | }
101 |
102 | int main(int argc, char** argv)
103 | {
104 | (void)argc;
105 | (void)argv;
106 |
107 | std::string pass;
108 |
109 | if (argc<3) {
110 | printf("Usage:%s host port pass \r\n", argv[0]);
111 | return -1;
112 | } else if (4==argc) {
113 | pass = argv[3];
114 | }
115 |
116 | init_timer();
117 | xRedisClusterClient redisclient;
118 | //redisclient.setLogLevel(LOG_LEVEL_DEBUG, log_demo);
119 | redis = &redisclient;
120 | bool bRet = redisclient.connect(argv[1], atoi(argv[2]), pass, 4);
121 |
122 | if (!bRet) {
123 | fprintf(stderr, "Connect to %s:%s error\r\n", argv[0], argv[1]);
124 | return -1;
125 | }
126 |
127 | std::string strInput;
128 | while (true) {
129 | cout << "\033[32mxRedis> \033[0m";
130 | getline(cin, strInput);
131 | if (!cin)
132 | return 0;
133 |
134 | if (strInput.length() < 1) {
135 | cout << "input again" << endl;
136 | } else {
137 | RedisResult result;
138 | VString vDataIn;
139 |
140 | str2Vect(strInput.c_str(), vDataIn, " ");
141 | redisclient.commandArgv(vDataIn, result);
142 |
143 | switch (result.type()) {
144 | case REDIS_REPLY_INTEGER: {
145 | printf("%lld \r\n", result.integer());
146 | break;
147 | }
148 | case REDIS_REPLY_NIL: {
149 | printf("%lld %s \r\n", result.integer(), result.str());
150 | break;
151 | }
152 | case REDIS_REPLY_STATUS: {
153 | printf("%s \r\n", result.str());
154 | break;
155 | }
156 | case REDIS_REPLY_ERROR: {
157 | printf("%s \r\n", result.str());
158 | break;
159 | }
160 | case REDIS_REPLY_STRING: {
161 | printf("%s \r\n", result.str());
162 | break;
163 | }
164 | case REDIS_REPLY_ARRAY: {
165 | for (size_t i = 0; i < result.elements(); ++i) {
166 | RedisResult::RedisReply reply = result.element(i);
167 | printf("type:%d integer:%lld str:%s \r\n",
168 | reply.type(), reply.integer(), reply.str());
169 | }
170 | break;
171 | }
172 | }
173 | }
174 | }
175 |
176 | return 0;
177 | }
178 |
--------------------------------------------------------------------------------
/examples/demo.cpp:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * ----------------------------------------------------------------------------
4 | * Copyright (c) 2013-2021, xSky
5 | * All rights reserved.
6 | * Distributed under GPL license.
7 | * ----------------------------------------------------------------------------
8 | */
9 |
10 | /** \example demo.cpp
11 | * This is an example of how to use the xRedis.
12 | *
This demo connect to single redis server with connection pool
13 | *
More details about this example.
14 | */
15 |
16 | #include "xRedisClient.h"
17 | #include
18 | #include
19 |
20 | using namespace xrc;
21 |
22 | enum {
23 | CACHE_TYPE_1,
24 | CACHE_TYPE_MAX,
25 | };
26 |
27 | /* 配置单个redis存储节点 */
28 | RedisNode RedisList1[1] = {
29 | { .dbindex = 0, .host = "127.0.0.1", .port = 6379, .passwd = "", .poolsize = 4, .timeout = 5, .role = MASTER }
30 | };
31 |
32 | void log_demo(int level, const char* line)
33 | {
34 | printf("xRedis %u %s", level, line);
35 | }
36 |
37 | int main(int argc, char** argv)
38 | {
39 | (void)argc;
40 | (void)argv;
41 |
42 | xRedisClient xRedis;
43 | //xRedis.SetLogLevel(LOG_LEVEL_DEBUG, log_demo );
44 | xRedis.Init(CACHE_TYPE_MAX);
45 | xRedis.ConnectRedisCache(RedisList1, sizeof(RedisList1) / sizeof(RedisNode),
46 | 1, CACHE_TYPE_1);
47 |
48 | const char* key = "test";
49 | const char* value = "test value";
50 | SliceIndex index(&xRedis, CACHE_TYPE_1);
51 | index.Create(key);
52 |
53 | bool bRet = xRedis.set(index, key, value);
54 | if (bRet) {
55 | printf("success \r\n");
56 | } else {
57 | printf("error %s \r\n", index.GetErrInfo());
58 | }
59 |
60 | std::string strValue;
61 | bRet = xRedis.get(index, key, strValue);
62 | if (bRet) {
63 | printf("%s \r\n", strValue.c_str());
64 | } else {
65 | printf("error %s ", index.GetErrInfo());
66 | }
67 |
68 | while (true)
69 | {
70 | usleep(1000*1000*6);
71 | xRedis.Keepalive();
72 | }
73 |
74 |
75 | return 0;
76 | }
77 |
--------------------------------------------------------------------------------
/examples/demo_multi_slice.cpp:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * ----------------------------------------------------------------------------
4 | * Copyright (c) 2013-2021, xSky
5 | * All rights reserved.
6 | * Distributed under GPL license.
7 | * ----------------------------------------------------------------------------
8 | */
9 |
10 | /** \example demo_multi_slice.cpp
11 | * This is an example of how to use the xRedis.
12 | *
connect to multi redis clusters
13 | *
every redis cluster have multi redis server nodes
14 | *
every redis node have a connection pool
15 | *
More details about this example.
16 | */
17 |
18 | #include
19 |
20 | #include "xRedisClient.h"
21 |
22 | using namespace xrc;
23 |
24 | enum {
25 | CACHE_TYPE_1,
26 | CACHE_TYPE_2,
27 | CACHE_TYPE_MAX,
28 | };
29 |
30 | /* 配置一个3分片存储xRedis集群 CACHE_TYPE_1:共3个存储主节点 */
31 | RedisNode RedisList1[3] = {
32 | { .dbindex = 0, .host = "127.0.0.1", .port = 6379, .passwd = "", .poolsize = 4, .timeout = 5, .role = MASTER },
33 | { .dbindex = 1, .host = "127.0.0.2", .port = 6379, .passwd = "", .poolsize = 4, .timeout = 5, .role = MASTER },
34 | { .dbindex = 2, .host = "127.0.0.3", .port = 6379, .passwd = "", .poolsize = 4, .timeout = 5, .role = MASTER }
35 | };
36 |
37 | /* 配置一个5分片存储xRedis集群 CACHE_TYPE_2:共5个存储主节点 */
38 | RedisNode RedisList2[5] = {
39 | { .dbindex = 0, .host = "127.0.0.1", .port = 6379, .passwd = "", .poolsize = 4, .timeout = 5, .role = MASTER },
40 | { .dbindex = 1, .host = "127.0.0.2", .port = 6379, .passwd = "", .poolsize = 4, .timeout = 5, .role = MASTER },
41 | { .dbindex = 2, .host = "127.0.0.3", .port = 6379, .passwd = "", .poolsize = 4, .timeout = 5, .role = MASTER },
42 | { .dbindex = 3, .host = "127.0.0.4", .port = 6379, .passwd = "", .poolsize = 4, .timeout = 5, .role = MASTER },
43 | { .dbindex = 4, .host = "127.0.0.5", .port = 6379, .passwd = "", .poolsize = 4, .timeout = 5, .role = MASTER },
44 | };
45 |
46 | int main(int argc, char** argv)
47 | {
48 | (void)argc;
49 | (void)argv;
50 |
51 | xRedisClient xRedis;
52 | xRedis.Init(CACHE_TYPE_MAX);
53 | xRedis.ConnectRedisCache(RedisList1, sizeof(RedisList1) / sizeof(RedisNode),
54 | 3, CACHE_TYPE_1);
55 | xRedis.ConnectRedisCache(RedisList2, sizeof(RedisList2) / sizeof(RedisNode),
56 | 5, CACHE_TYPE_2);
57 |
58 | const char* key = "test";
59 | const char* value = "test value";
60 |
61 | SliceIndex index(&xRedis, CACHE_TYPE_1);
62 | bool bRet = index.Create(key);
63 | if (!bRet) {
64 | return 0;
65 | }
66 |
67 | bRet = xRedis.set(index, key, value);
68 | if (bRet) {
69 | printf("success \r\n");
70 | } else {
71 | printf("error [%s] \r\n", index.GetErrInfo());
72 | }
73 |
74 | std::string strValue;
75 | bRet = xRedis.get(index, key, strValue);
76 | if (bRet) {
77 | printf("%s \r\n", strValue.c_str());
78 | } else {
79 | printf("error [%s] \r\n", index.GetErrInfo());
80 | }
81 |
82 | return 0;
83 | }
84 |
--------------------------------------------------------------------------------
/examples/demo_slice.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * ----------------------------------------------------------------------------
3 | * Copyright (c) 2013-2021, xSky
4 | * All rights reserved.
5 | * Distributed under GPL license.
6 | * ----------------------------------------------------------------------------
7 | */
8 |
9 | /** \example demo_slice.cpp
10 | * This is an example of how to use the xRedis.
11 | *
Connect to a redis cluster which contains three redis node
12 | *
More details about this example.
13 | */
14 |
15 | #include "xRedisClient.h"
16 | #include
17 |
18 | using namespace xrc;
19 |
20 | enum {
21 | CACHE_TYPE_1,
22 | CACHE_TYPE_2,
23 | CACHE_TYPE_MAX,
24 | };
25 |
26 | /* 配置一个3分片存储xRedis集群:共3个存储主节点 */
27 | RedisNode RedisList1[3] = {
28 | { .dbindex = 0, .host = "127.0.0.1", .port = 6379, .passwd = "", .poolsize = 4, .timeout = 5, .role = MASTER },
29 | { .dbindex = 1, .host = "127.0.0.2", .port = 6379, .passwd = "", .poolsize = 4, .timeout = 5, .role = MASTER },
30 | { .dbindex = 2, .host = "127.0.0.3", .port = 6379, .passwd = "", .poolsize = 4, .timeout = 5, .role = MASTER }
31 | };
32 |
33 | int main(int argc, char** argv)
34 | {
35 | (void)argc;
36 | (void)argv;
37 |
38 | xRedisClient xRedis;
39 | xRedis.Init(CACHE_TYPE_MAX);
40 | xRedis.ConnectRedisCache(RedisList1, sizeof(RedisList1) / sizeof(RedisNode),
41 | 3, CACHE_TYPE_1);
42 |
43 | const char* key = "test";
44 | const char* value = "test value";
45 |
46 | SliceIndex index(&xRedis, CACHE_TYPE_1);
47 | bool bRet = index.Create(key);
48 | if (!bRet) {
49 | return 0;
50 | }
51 |
52 | bRet = xRedis.set(index, key, value);
53 | if (bRet) {
54 | printf("success \r\n");
55 | } else {
56 | printf("error [%s] \r\n", index.GetErrInfo());
57 | }
58 |
59 | std::string strValue;
60 | bRet = xRedis.get(index, key, strValue);
61 | if (bRet) {
62 | printf("%s \r\n", strValue.c_str());
63 | } else {
64 | printf("error [%s] \r\n", index.GetErrInfo());
65 | }
66 |
67 | return 0;
68 | }
69 |
--------------------------------------------------------------------------------
/examples/redis-cluster-client.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * ----------------------------------------------------------------------------
3 | * Copyright (c) 2013-2021, xSky
4 | * All rights reserved.
5 | * Distributed under GPL license.
6 | * ----------------------------------------------------------------------------
7 | */
8 |
9 | /** \example redis-cluster-client.cpp
10 | * This is an example of how to use the xRedis.
11 | *
This demo connect to single redis server with connection pool
12 | *
More details about this example.
13 | */
14 |
15 | #include "xRedisClusterClient.h"
16 | #include
17 | #include
18 | #include
19 | #include
20 |
21 | using std::cin;
22 | using std::cout;
23 | using std::endl;
24 |
25 | /*
26 | 这是连接redis官方集群客户端的一个示例
27 | */
28 |
29 | int main(int argc, char** argv)
30 | {
31 | (void)argc;
32 | (void)argv;
33 |
34 | xRedisClusterClient ClusterClient;
35 |
36 | bool bRet = ClusterClient.Connect(argv[1], atoi(argv[2]), 2);
37 | if (!bRet) {
38 | return -1;
39 | }
40 |
41 | std::string strInput;
42 | while (true) {
43 | cout << "\033[32mxRedis> \033[0m";
44 | getline(cin, strInput);
45 | if (!cin)
46 | return 0;
47 |
48 | if (strInput.length() < 1) {
49 | cout << "input again" << endl;
50 | } else {
51 | RedisResult result;
52 | VSTRING vDataIn;
53 |
54 | xRedisClusterClient::str2Vect(strInput.c_str(), vDataIn, " ");
55 | ClusterClient.RedisCommandArgv(vDataIn, result);
56 |
57 | switch (result.type()) {
58 | case REDIS_REPLY_INTEGER: {
59 | printf("%lld \r\n", result.integer());
60 | break;
61 | }
62 | case REDIS_REPLY_NIL: {
63 | printf("%lld %s \r\n", result.integer(), result.str());
64 | break;
65 | }
66 | case REDIS_REPLY_STATUS: {
67 | printf("%s \r\n", result.str());
68 | break;
69 | }
70 | case REDIS_REPLY_ERROR: {
71 | printf("%s \r\n", result.str());
72 | break;
73 | }
74 | case REDIS_REPLY_STRING: {
75 | printf("%s \r\n", result.str());
76 | break;
77 | }
78 | case REDIS_REPLY_ARRAY: {
79 | for (size_t i = 0; i < result.elements(); ++i) {
80 | RedisResult::RedisReply reply = result.element(i);
81 | printf("type:%d integer:%lld str:%s \r\n", reply.type(),
82 | reply.integer(), reply.str());
83 | }
84 | break;
85 | }
86 | }
87 | }
88 | }
89 |
90 | return 0;
91 | }
92 |
--------------------------------------------------------------------------------
/examples/xRedisClusterClient_test.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * ----------------------------------------------------------------------------
3 | * Copyright (c) 2013-2021, xSky
4 | * All rights reserved.
5 | * Distributed under GPL license.
6 | * ----------------------------------------------------------------------------
7 | */
8 |
9 | /** \example xRedisClusterClient_test.cpp
10 | * This is an example of how to use the xRedis.
11 | *
This demo connect to single redis server with connection pool
12 | *
More details about this example.
13 | */
14 |
15 | #include
16 | #include
17 | #include
18 | #include
19 |
20 | #include "xRedisClusterClient.h"
21 |
22 | using namespace xrc;
23 |
24 | int main(int argc, char** argv)
25 | {
26 | (void)argc;
27 | (void)argv;
28 |
29 | xRedisClusterClient redisClusterClient;
30 | std::string pass;
31 | bool bRet = redisClusterClient.connect("127.0.0.1", 7001, pass, 4);
32 | //bool bRet = redisClusterClient.ConnectRedis(argv[1], atoi(argv[2]), argv[3], 4);
33 | if (!bRet) {
34 | return -1;
35 | }
36 |
37 | // VSTRING redis_arg;
38 | // redis_arg.push_back("hgetall");
39 | // redis_arg.push_back("htest");
40 |
41 | RedisResult result;
42 | redisClusterClient.command(result, "hgetall %s", "htest");
43 |
44 | printf("type:%d integer:%lld str:%s \r\n", result.type(), result.integer(),
45 | result.str());
46 |
47 | for (size_t i = 0; i < result.elements(); ++i) {
48 | RedisResult::RedisReply reply = result.element(i);
49 | printf("type:%d integer:%lld str:%s \r\n", reply.type(), reply.integer(),
50 | reply.str());
51 | }
52 |
53 | while (true) {
54 | usleep(1000 * 1000 * 6);
55 | redisClusterClient.keepalive();
56 | }
57 |
58 | return 0;
59 | }
60 |
--------------------------------------------------------------------------------
/examples/xredis-example-Consistent-hash/CMd5.cpp:
--------------------------------------------------------------------------------
1 | #include "CMd5.h"
2 | #include
3 | #include
4 |
5 | #undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
6 | #ifdef ARCH_IS_BIG_ENDIAN
7 | # define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
8 | #else
9 | # define BYTE_ORDER 0
10 | #endif
11 |
12 | #define T_MASK ((md5_word_t)~0)
13 | #define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
14 | #define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
15 | #define T3 0x242070db
16 | #define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
17 | #define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
18 | #define T6 0x4787c62a
19 | #define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
20 | #define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
21 | #define T9 0x698098d8
22 | #define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
23 | #define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
24 | #define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
25 | #define T13 0x6b901122
26 | #define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
27 | #define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
28 | #define T16 0x49b40821
29 | #define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
30 | #define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
31 | #define T19 0x265e5a51
32 | #define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
33 | #define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
34 | #define T22 0x02441453
35 | #define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
36 | #define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
37 | #define T25 0x21e1cde6
38 | #define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
39 | #define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
40 | #define T28 0x455a14ed
41 | #define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
42 | #define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
43 | #define T31 0x676f02d9
44 | #define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
45 | #define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
46 | #define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
47 | #define T35 0x6d9d6122
48 | #define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
49 | #define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
50 | #define T38 0x4bdecfa9
51 | #define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
52 | #define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
53 | #define T41 0x289b7ec6
54 | #define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
55 | #define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
56 | #define T44 0x04881d05
57 | #define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
58 | #define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
59 | #define T47 0x1fa27cf8
60 | #define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
61 | #define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
62 | #define T50 0x432aff97
63 | #define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
64 | #define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
65 | #define T53 0x655b59c3
66 | #define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
67 | #define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
68 | #define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
69 | #define T57 0x6fa87e4f
70 | #define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
71 | #define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
72 | #define T60 0x4e0811a1
73 | #define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
74 | #define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
75 | #define T63 0x2ad7d2bb
76 | #define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
77 |
78 |
79 | static void
80 | md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
81 | {
82 | md5_word_t
83 | a = pms->abcd[0], b = pms->abcd[1],
84 | c = pms->abcd[2], d = pms->abcd[3];
85 | md5_word_t t;
86 | #if BYTE_ORDER > 0
87 | /* Define storage only for big-endian CPUs. */
88 | md5_word_t X[16];
89 | #else
90 | /* Define storage for little-endian or both types of CPUs. */
91 | md5_word_t xbuf[16];
92 | const md5_word_t *X;
93 | #endif
94 |
95 | {
96 | #if BYTE_ORDER == 0
97 | /*
98 | * Determine dynamically whether this is a big-endian or
99 | * little-endian machine, since we can use a more efficient
100 | * algorithm on the latter.
101 | */
102 | static const int w = 1;
103 |
104 | if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
105 | #endif
106 | #if BYTE_ORDER <= 0 /* little-endian */
107 | {
108 | /*
109 | * On little-endian machines, we can process properly aligned
110 | * data without copying it.
111 | */
112 | if (!((data - (const md5_byte_t *)0) & 3)) {
113 | /* data are properly aligned */
114 | X = (const md5_word_t *)data;
115 | } else {
116 | /* not aligned */
117 | memcpy(xbuf, data, 64);
118 | X = xbuf;
119 | }
120 | }
121 | #endif
122 | #if BYTE_ORDER == 0
123 | else /* dynamic big-endian */
124 | #endif
125 | #if BYTE_ORDER >= 0 /* big-endian */
126 | {
127 | /*
128 | * On big-endian machines, we must arrange the bytes in the
129 | * right order.
130 | */
131 | const md5_byte_t *xp = data;
132 | int i;
133 |
134 | # if BYTE_ORDER == 0
135 | X = xbuf; /* (dynamic only) */
136 | # else
137 | # define xbuf X /* (static only) */
138 | # endif
139 | for (i = 0; i < 16; ++i, xp += 4)
140 | xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
141 | }
142 | #endif
143 | }
144 |
145 | #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
146 |
147 | /* Round 1. */
148 | /* Let [abcd k s i] denote the operation
149 | a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
150 | #define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
151 | #define SET(a, b, c, d, k, s, Ti)\
152 | t = a + F(b,c,d) + X[k] + Ti;\
153 | a = ROTATE_LEFT(t, s) + b
154 | /* Do the following 16 operations. */
155 | SET(a, b, c, d, 0, 7, T1);
156 | SET(d, a, b, c, 1, 12, T2);
157 | SET(c, d, a, b, 2, 17, T3);
158 | SET(b, c, d, a, 3, 22, T4);
159 | SET(a, b, c, d, 4, 7, T5);
160 | SET(d, a, b, c, 5, 12, T6);
161 | SET(c, d, a, b, 6, 17, T7);
162 | SET(b, c, d, a, 7, 22, T8);
163 | SET(a, b, c, d, 8, 7, T9);
164 | SET(d, a, b, c, 9, 12, T10);
165 | SET(c, d, a, b, 10, 17, T11);
166 | SET(b, c, d, a, 11, 22, T12);
167 | SET(a, b, c, d, 12, 7, T13);
168 | SET(d, a, b, c, 13, 12, T14);
169 | SET(c, d, a, b, 14, 17, T15);
170 | SET(b, c, d, a, 15, 22, T16);
171 | #undef SET
172 |
173 | /* Round 2. */
174 | /* Let [abcd k s i] denote the operation
175 | a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
176 | #define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
177 | #define SET(a, b, c, d, k, s, Ti)\
178 | t = a + G(b,c,d) + X[k] + Ti;\
179 | a = ROTATE_LEFT(t, s) + b
180 | /* Do the following 16 operations. */
181 | SET(a, b, c, d, 1, 5, T17);
182 | SET(d, a, b, c, 6, 9, T18);
183 | SET(c, d, a, b, 11, 14, T19);
184 | SET(b, c, d, a, 0, 20, T20);
185 | SET(a, b, c, d, 5, 5, T21);
186 | SET(d, a, b, c, 10, 9, T22);
187 | SET(c, d, a, b, 15, 14, T23);
188 | SET(b, c, d, a, 4, 20, T24);
189 | SET(a, b, c, d, 9, 5, T25);
190 | SET(d, a, b, c, 14, 9, T26);
191 | SET(c, d, a, b, 3, 14, T27);
192 | SET(b, c, d, a, 8, 20, T28);
193 | SET(a, b, c, d, 13, 5, T29);
194 | SET(d, a, b, c, 2, 9, T30);
195 | SET(c, d, a, b, 7, 14, T31);
196 | SET(b, c, d, a, 12, 20, T32);
197 | #undef SET
198 |
199 | /* Round 3. */
200 | /* Let [abcd k s t] denote the operation
201 | a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
202 | #define H(x, y, z) ((x) ^ (y) ^ (z))
203 | #define SET(a, b, c, d, k, s, Ti)\
204 | t = a + H(b,c,d) + X[k] + Ti;\
205 | a = ROTATE_LEFT(t, s) + b
206 | /* Do the following 16 operations. */
207 | SET(a, b, c, d, 5, 4, T33);
208 | SET(d, a, b, c, 8, 11, T34);
209 | SET(c, d, a, b, 11, 16, T35);
210 | SET(b, c, d, a, 14, 23, T36);
211 | SET(a, b, c, d, 1, 4, T37);
212 | SET(d, a, b, c, 4, 11, T38);
213 | SET(c, d, a, b, 7, 16, T39);
214 | SET(b, c, d, a, 10, 23, T40);
215 | SET(a, b, c, d, 13, 4, T41);
216 | SET(d, a, b, c, 0, 11, T42);
217 | SET(c, d, a, b, 3, 16, T43);
218 | SET(b, c, d, a, 6, 23, T44);
219 | SET(a, b, c, d, 9, 4, T45);
220 | SET(d, a, b, c, 12, 11, T46);
221 | SET(c, d, a, b, 15, 16, T47);
222 | SET(b, c, d, a, 2, 23, T48);
223 | #undef SET
224 |
225 | /* Round 4. */
226 | /* Let [abcd k s t] denote the operation
227 | a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
228 | #define I(x, y, z) ((y) ^ ((x) | ~(z)))
229 | #define SET(a, b, c, d, k, s, Ti)\
230 | t = a + I(b,c,d) + X[k] + Ti;\
231 | a = ROTATE_LEFT(t, s) + b
232 | /* Do the following 16 operations. */
233 | SET(a, b, c, d, 0, 6, T49);
234 | SET(d, a, b, c, 7, 10, T50);
235 | SET(c, d, a, b, 14, 15, T51);
236 | SET(b, c, d, a, 5, 21, T52);
237 | SET(a, b, c, d, 12, 6, T53);
238 | SET(d, a, b, c, 3, 10, T54);
239 | SET(c, d, a, b, 10, 15, T55);
240 | SET(b, c, d, a, 1, 21, T56);
241 | SET(a, b, c, d, 8, 6, T57);
242 | SET(d, a, b, c, 15, 10, T58);
243 | SET(c, d, a, b, 6, 15, T59);
244 | SET(b, c, d, a, 13, 21, T60);
245 | SET(a, b, c, d, 4, 6, T61);
246 | SET(d, a, b, c, 11, 10, T62);
247 | SET(c, d, a, b, 2, 15, T63);
248 | SET(b, c, d, a, 9, 21, T64);
249 | #undef SET
250 |
251 | /* Then perform the following additions. (That is increment each
252 | of the four registers by the value it had before this block
253 | was started.) */
254 | pms->abcd[0] += a;
255 | pms->abcd[1] += b;
256 | pms->abcd[2] += c;
257 | pms->abcd[3] += d;
258 | }
259 |
260 | void
261 | md5_init(md5_state_t *pms)
262 | {
263 | pms->count[0] = pms->count[1] = 0;
264 | pms->abcd[0] = 0x67452301;
265 | pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
266 | pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
267 | pms->abcd[3] = 0x10325476;
268 | }
269 |
270 | void
271 | md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
272 | {
273 | const md5_byte_t *p = data;
274 | int left = nbytes;
275 | int offset = (pms->count[0] >> 3) & 63;
276 | md5_word_t nbits = (md5_word_t)(nbytes << 3);
277 |
278 | if (nbytes <= 0)
279 | return;
280 |
281 | /* Update the message length. */
282 | pms->count[1] += nbytes >> 29;
283 | pms->count[0] += nbits;
284 | if (pms->count[0] < nbits)
285 | pms->count[1]++;
286 |
287 | /* Process an initial partial block. */
288 | if (offset) {
289 | int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
290 |
291 | memcpy(pms->buf + offset, p, copy);
292 | if (offset + copy < 64)
293 | return;
294 | p += copy;
295 | left -= copy;
296 | md5_process(pms, pms->buf);
297 | }
298 |
299 | /* Process full blocks. */
300 | for (; left >= 64; p += 64, left -= 64)
301 | md5_process(pms, p);
302 |
303 | /* Process a final partial block. */
304 | if (left)
305 | memcpy(pms->buf, p, left);
306 | }
307 |
308 | void
309 | md5_finish(md5_state_t *pms, md5_byte_t digest[16])
310 | {
311 | static const md5_byte_t pad[64] = {
312 | 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
313 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
314 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
315 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
316 | };
317 | md5_byte_t data[8];
318 | int i;
319 |
320 | /* Save the length before padding. */
321 | for (i = 0; i < 8; ++i)
322 | data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
323 | /* Pad to 56 bytes mod 64. */
324 | md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
325 | /* Append the length. */
326 | md5_append(pms, data, 8);
327 | for (i = 0; i < 16; ++i)
328 | digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
329 | }
330 |
331 | void getMd5String(char *inbuf, md5_byte_t digest[16])
332 | {
333 | for (int j = 0; j < 16; j++) {
334 | sprintf(inbuf + j * 2, "%02x", ((unsigned char*)digest)[j]);
335 | }
336 | }
337 |
338 | void getMd5Str(const char *str, char *strhash)
339 | {
340 | unsigned char digest[16];
341 | md5_state_t md5state;
342 | md5_init(&md5state);
343 | md5_append(&md5state, (const unsigned char *)str, strlen(str));
344 | md5_finish(&md5state, digest);
345 |
346 | getMd5String(strhash, digest);
347 | }
348 |
349 |
--------------------------------------------------------------------------------
/examples/xredis-example-Consistent-hash/CMd5.h:
--------------------------------------------------------------------------------
1 | #ifndef md5_INCLUDED
2 | #define md5_INCLUDED
3 |
4 | typedef unsigned char md5_byte_t; /* 8-bit byte */
5 | typedef unsigned int md5_word_t; /* 32-bit word */
6 |
7 | /* Define the state of the MD5 Algorithm. */
8 | typedef struct md5_state_s {
9 | md5_word_t count[2]; /* message length in bits, lsw first */
10 | md5_word_t abcd[4]; /* digest buffer */
11 | md5_byte_t buf[64]; /* accumulate block */
12 | } md5_state_t;
13 |
14 | void md5_init(md5_state_t *pms);
15 | void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
16 | void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
17 | void getMd5String(char *inbuf, md5_byte_t digest[16]);
18 | void getMd5Str(const char *str, char *strhash);
19 |
20 | #endif /* md5_INCLUDED */
21 |
--------------------------------------------------------------------------------
/examples/xredis-example-Consistent-hash/redis-test.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #include "CMd5.h"
6 | #include "xRedisClient.h"
7 |
8 | // AP Hash Function
9 | unsigned int APHash(const char* str)
10 | {
11 | unsigned int hash = 0;
12 | int i;
13 |
14 | for (i = 0; *str; i++) {
15 | if ((i & 1) == 0) {
16 | hash ^= ((hash << 7) ^ (*str++) ^ (hash >> 3));
17 | } else {
18 | hash ^= (~((hash << 11) ^ (*str++) ^ (hash >> 5)));
19 | }
20 | }
21 |
22 | return (hash & 0x7FFFFFFF);
23 | }
24 |
25 | #include
26 | #include