腾讯云分布式缓存数据库 C 连接示例

使用 C 语言客户端通过代理模式和直连模式连接腾讯云分布式缓存数据库实例的示例。

相关产品
腾讯云分布式缓存数据库(兼容 Redis) 产品页,含版本规格、价格与购买入口。

一、环境要求

·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); // 设置带过期时间的 Key reply = 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}; // 初始化 SSL redisInitOpenSSL(); // 创建 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 基础连接示例

#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 account const 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。

赞 (0)
上一篇 4天前
下一篇 4天前