本文介绍使用 C 语言客户端通过代理模式和直连模式连接腾讯云分布式缓存数据库实例的示例。
准备工作
环境要求
GCC 4.8及以上版本。
CMake 或 Make 构建工具。
安装客户端
推荐使用 hiredis(Redis 官方 C 客户端)和 hiredis-cluster(集群支持):
安装 hiredis
git clone https://github.com/redis/hiredis.gitcd hiredismakesudo make install
安装 hiredis-cluster(直连模式需要)
git clone https://github.com/Nordix/hiredis-cluster.gitcd hiredis-clustermkdir build && cd buildcmake ..makesudo make install
编译链接
# 代理模式gcc -o redis_example redis_example.c -lhiredis# 直连模式gcc -o redis_cluster_example redis_cluster_example.c -lhiredis_cluster -lhiredis
获取连接信息
1. 登录 分布式缓存数据库控制台。
2. 在实例列表中,单击目标实例 ID,进入实例详情页。
3. 在网络信息区域,获取实例 VIP 地址和端口(默认6379)。
4. 在配置信息区域,获取实例的连接密码。
默认账号使用
实例 ID:密码 格式,自定义账号使用 用户名@密码 格式;免密认证实例无需密码。代理模式连接示例
代理模式下,客户端通过 Proxy 代理层提供的统一 VIP 地址连接实例,Proxy 自动处理请求路由和故障转移,客户端无需感知后端拓扑变化。
hiredis 基础连接示例
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <hiredis/hiredis.h>int main() {// 连接参数const char *host = "192.xx.xx.2"; // 实例 VIP 地址int port = 6379; // 实例端口const char *password = "crs-xxxx:密码"; // 默认账号密码格式:实例ID:密码struct timeval timeout = {2, 0}; // 连接超时 2 秒// 建立连接redisContext *c = redisConnectWithTimeout(host, port, timeout);if (c == NULL || c->err) {if (c) {printf("Connection error: %s\\n", c->errstr);redisFree(c);} else {printf("Connection error: can't allocate redis context\\n");}return 1;}// 认证redisReply *reply = redisCommand(c, "AUTH %s", password);if (reply == NULL || reply->type == REDIS_REPLY_ERROR) {printf("Auth failed: %s\\n", reply ? reply->str : "unknown error");freeReplyObject(reply);redisFree(c);return 1;}freeReplyObject(reply);// 写入数据reply = redisCommand(c, "SET name %s", "腾讯云分布式缓存数据库");printf("SET result: %s\\n", reply->str);freeReplyObject(reply);// 读取数据reply = redisCommand(c, "GET name");printf("GET name: %s\\n", reply->str);freeReplyObject(reply);// 设置带过期时间的 Keyreply = redisCommand(c, "SETEX session:user123 3600 %s", "session_data");printf("SETEX result: %s\\n", reply->str);freeReplyObject(reply);// 哈希操作reply = redisCommand(c, "HSET user:1001 name %s age %s", "张三", "28");printf("HSET result: %lld\\n", reply->integer);freeReplyObject(reply);reply = redisCommand(c, "HGET user:1001 name");printf("HGET name: %s\\n", reply->str);freeReplyObject(reply);// 列表操作reply = redisCommand(c, "LPUSH queue:tasks %s %s %s", "task1", "task2", "task3");printf("LPUSH result: %lld\\n", reply->integer);freeReplyObject(reply);reply = redisCommand(c, "RPOP queue:tasks");printf("RPOP: %s\\n", reply->str);freeReplyObject(reply);// 关闭连接redisFree(c);return 0;}
SSL 加密连接示例
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <hiredis/hiredis.h>#include <hiredis/hiredis_ssl.h>int main() {const char *host = "192.xx.xx.2";int port = 6379;const char *password = "crs-xxxx:密码";const char *ca_cert = "/path/to/ca.pem";struct timeval timeout = {2, 0};// 初始化 SSLredisInitOpenSSL();// 创建 SSL 上下文redisSSLContext *ssl_context = redisCreateSSLContext(ca_cert, // CA 证书NULL, // 客户端证书(不需要)NULL, // 客户端私钥(不需要)NULL, // 证书密码NULL, // 错误信息NULL // 错误信息长度);if (ssl_context == NULL) {printf("Failed to create SSL context\\n");return 1;}// 建立 SSL 连接redisContext *c = redisConnectWithTimeout(host, port, timeout);if (c == NULL || c->err) {printf("Connection error: %s\\n", c ? c->errstr : "unknown");redisFreeSSLContext(ssl_context);if (c) redisFree(c);return 1;}// 初始化 SSL 连接if (redisInitiateSSLWithContext(c, ssl_context) != REDIS_OK) {printf("SSL init error: %s\\n", c->errstr);redisFreeSSLContext(ssl_context);redisFree(c);return 1;}// 认证redisReply *reply = redisCommand(c, "AUTH %s", password);if (reply == NULL || reply->type == REDIS_REPLY_ERROR) {printf("Auth failed: %s\\n", reply ? reply->str : "unknown");if (reply) freeReplyObject(reply);redisFreeSSLContext(ssl_context);redisFree(c);return 1;}freeReplyObject(reply);// 操作数据reply = redisCommand(c, "SET ssl_test %s", "encrypted_connection");printf("SET: %s\\n", reply->str);freeReplyObject(reply);reply = redisCommand(c, "GET ssl_test");printf("GET: %s\\n", reply->str);freeReplyObject(reply);// 清理资源redisFree(c);redisFreeSSLContext(ssl_context);return 0;}
直连模式连接示例
直连模式下,客户端使用 Redis Cluster 协议直接连接各分片节点,本地处理 MOVED/ASK 重定向,可直接使用社区标准的 Redis Cluster 客户端接入。
说明:
直连模式仅适用于集群架构实例。
需使用 hiredis-cluster 库(基于 hiredis 的集群扩展)。
需在控制台开启直连模式并获取各分片节点的连接地址。
认证方式复用 Redis 原生 ACL 机制:默认账号仅传密码,自定义账号需分别设置账号名与密码,不支持
用户名@密码 拼接格式。直连模式暂不支持 SSL 加密连接。
hiredis-cluster 基础连接示例
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <hiredis/hiredis.h>#include <hiredis_cluster/hircluster.h>int main() {// 直连模式下各分片节点地址const char *nodes = "192.xx.xx.2:6379,192.xx.xx.3:6379,192.xx.xx.4:6379";const char *password = "password"; // 直连模式默认账号仅传密码,不带实例 ID 前缀struct timeval timeout = {2, 0};// 创建集群连接上下文redisClusterContext *cc = redisClusterContextInit();if (cc == NULL) {printf("Failed to init cluster context\\n");return 1;}// 设置连接超时redisClusterSetOptionTimeout(cc, timeout);// 设置密码redisClusterSetOptionPassword(cc, password);// 设置最大重定向次数redisClusterSetOptionMaxRedirect(cc, 3);// 连接集群if (redisClusterSetOptionAddNodes(cc, nodes) != REDIS_OK) {printf("Failed to set nodes\\n");redisClusterFree(cc);return 1;}if (redisClusterConnect2(cc) != REDIS_OK) {printf("Connection error: %s\\n", cc->errstr);redisClusterFree(cc);return 1;}// 写入数据(客户端自动路由到正确的分片)redisReply *reply = redisClusterCommand(cc, "SET cluster:key1 %s", "value1");printf("SET key1: %s\\n", reply->str);freeReplyObject(reply);reply = redisClusterCommand(cc, "SET cluster:key2 %s", "value2");printf("SET key2: %s\\n", reply->str);freeReplyObject(reply);// 读取数据reply = redisClusterCommand(cc, "GET cluster:key1");printf("GET key1: %s\\n", reply->str);freeReplyObject(reply);reply = redisClusterCommand(cc, "GET cluster:key2");printf("GET key2: %s\\n", reply->str);freeReplyObject(reply);// 哈希操作reply = redisClusterCommand(cc, "HSET user:{1001} name %s age %s", "张三", "28");printf("HSET: %lld\\n", reply->integer);freeReplyObject(reply);reply = redisClusterCommand(cc, "HGET user:{1001} name");printf("HGET name: %s\\n", reply->str);freeReplyObject(reply);// 使用 Hash Tag 确保相关 Key 路由到同一分片reply = redisClusterCommand(cc, "SET {order:1001}:status %s", "paid");printf("SET order status: %s\\n", reply->str);freeReplyObject(reply);reply = redisClusterCommand(cc, "SET {order:1001}:amount %s", "99.00");printf("SET order amount: %s\\n", reply->str);freeReplyObject(reply);reply = redisClusterCommand(cc, "GET {order:1001}:status");printf("GET order status: %s\\n", reply->str);freeReplyObject(reply);// 关闭连接redisClusterFree(cc);return 0;}
自定义账号(ACL)连接示例
直连模式复用 Redis 原生 ACL 认证机制,使用自定义账号时需分别设置账号名与密码,不支持
用户名@密码 拼接格式。#include <stdio.h>#include <stdlib.h>#include <string.h>#include <hiredis/hiredis.h>#include <hiredis_cluster/hircluster.h>int main() {const char *nodes = "192.xx.xx.2:6379,192.xx.xx.3:6379,192.xx.xx.4:6379";// ===== ACL 认证机制:账号名与密码是两个独立字段 =====// 直连模式的多账号能力基于 Redis 原生 ACL:控制台创建的每个自定义账号// 都是一个独立的 ACL user,认证时客户端向节点发送 AUTH <account> <password>。const char *username = "myuser"; // ACL 账号名 → AUTH accountconst char *password = "MyPassword"; // 账号密码 → AUTH password(纯密码,无需拼接)struct timeval timeout = {2, 0};redisClusterContext *cc = redisClusterContextInit();redisClusterSetOptionTimeout(cc, timeout);// 分别设置账号名与密码(等价于执行 AUTH account password);// 不要写成代理模式的 "myuser@MyPassword" 拼接格式。redisClusterSetOptionUsername(cc, username);redisClusterSetOptionPassword(cc, password);redisClusterSetOptionMaxRedirect(cc, 3);redisClusterSetOptionAddNodes(cc, nodes);if (redisClusterConnect2(cc) != REDIS_OK) {printf("Connection error: %s\\n", cc->errstr);redisClusterFree(cc);return 1;}redisReply *reply = redisClusterCommand(cc, "SET key %s", "value");printf("SET: %s\\n", reply->str);freeReplyObject(reply);reply = redisClusterCommand(cc, "GET key");printf("GET: %s\\n", reply->str);freeReplyObject(reply);redisClusterFree(cc);return 0;}
连接参数说明
参数 | 说明 | 推荐值 |
host | 实例连接地址。代理模式为 VIP 地址,直连模式为分片节点地址 | - |
port | 实例端口号 | 6379 |
timeout | 连接超时时间 | 2 秒 |
password | 认证密码 | 默认账号格式: 实例 ID:密码 |
max_redirect | 最大重定向次数 | 3 |
常见问题
连接超时
确认客户端所在 CVM 与分布式缓存数据库实例在同一 VPC 内。
确认安全组规则已放通对应端口。
确认连接地址和端口正确。
认证失败
代理模式:默认账号使用
实例 ID:密码,自定义账号使用 用户名@密码。直连模式:复用 Redis ACL 认证,默认账号仅传密码(
AUTH password),自定义账号需分别设置账号名与密码(AUTH account password),不支持 用户名@密码 拼接格式。确认密码中无特殊字符导致解析异常。
直连模式 MOVED 错误
确认使用 hiredis-cluster 的
redisClusterCommand 而非 hiredis 的 redisCommand。确认已在控制台开启直连模式。
确认节点地址为分片节点地址而非 VIP 地址。
编译链接错误
确认 hiredis 和 hiredis-cluster 已正确安装。
确认链接时指定了
-lhiredis 和 -lhiredis_cluster。