更多技术干货尽在公众号“系统编程语言”。
在 C 语言中使用 Redis 存储复杂结构体可以通过序列化和反序列化来实现。Redis 本身支持字符串、哈希、列表、集合等数据类型,但这些类型主要用于存储简单的数据。为了存储复杂的结构体,通常需要将结构体序列化为字符串或 JSON 格式,然后再存储到 Redis 中。
以下是一个示例,展示如何使用 C 语言和 Redis 存储和检索复杂结构体。
1. 安装 Redis 和 Redis C 客户端
首先,确保你已经安装了 Redis 服务器和 Redis C 客户端库(如 hiredis
)。
sudo apt-get update
sudo apt-get install redis-server
sudo apt-get install libhiredis-dev
2. 定义复杂结构体
假设我们有一个复杂的结构体,包含嵌套的结构体和数组。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <hiredis/hiredis.h>
typedef struct {
char name[50];
int age;
} Person;
typedef struct {
char title[100];
Person* members;
int member_count;
} Team;
3. 序列化和反序列化
我们需要编写函数来将 Team
结构体序列化为字符串,并从字符串反序列化回 Team
结构体。
#include <jansson.h> // JSON 库
char* serialize_team(Team* team) {
json_t *root, *members_array, *member_obj;
json_error_t error;
root = json_object();
members_array = json_array();
json_object_set_new(root, "title", json_string(team->title));
for (int i = 0; i < team->member_count; i++) {
member_obj = json_object();
json_object_set_new(member_obj, "name", json_string(team->members[i].name));
json_object_set_new(member_obj, "age", json_integer(team->members[i].age));
json_array_append_new(members_array, member_obj);
}
json_object_set_new(root, "members", members_array);
char *json_str = json_dumps(root, JSON_COMPACT);
json_decref(root);
return json_str;
}
Team* deserialize_team(const char* json_str) {
json_error_t error;
json_t *root, *members_array, *member_obj;
Team *team = (Team*)malloc(sizeof(Team));
root = json_loads(json_str, 0, &error);
if (!root) {
fprintf(stderr, "Error parsing JSON: %s\n", error.text);
return NULL;
}
const char *title = json_string_value(json_object_get(root, "title"));
strncpy(team->title, title, sizeof(team->title) - 1);
members_array = json_array_get(root, "members");
team->member_count = json_array_size(members_array);
team->members = (Person*)malloc(team->member_count * sizeof(Person));
for (int i = 0; i < team->member_count; i++) {
member_obj = json_array_get(members_array, i);
const char *name = json_string_value(json_object_get(member_obj, "name"));
int age = json_integer_value(json_object_get(member_obj, "age"));
strncpy(team->members[i].name, name, sizeof(team->members[i].name) - 1);
team->members[i].age = age;
}
json_decref(root);
return team;
}
4. 存储和检索复杂结构体
使用 hiredis
库将序列化后的字符串存储到 Redis 中,并从 Redis 中检索并反序列化回 Team
结构体。
int main() {
redisContext *c = redisConnect("127.0.0.1", 6379);
if (c == NULL || c->err) {
if (c) {
printf("Error: %s\n", c->errstr);
redisFree(c);
} else {
printf("Can't allocate redis context\n");
}
return 1;
}
// 创建一个 Team 结构体
Team team;
strcpy(team.title, "Development Team");
team.member_count = 2;
team.members = (Person*)malloc(team.member_count * sizeof(Person));
strcpy(team.members[0].name, "Alice");
team.members[0].age = 30;
strcpy(team.members[1].name, "Bob");
team.members[1].age = 35;
// 序列化 Team 结构体
char *json_str = serialize_team(&team);
// 存储到 Redis
redisReply *reply = (redisReply*)redisCommand(c, "SET team_data %s", json_str);
if (reply->type == REDIS_REPLY_ERROR) {
printf("Error setting data: %s\n", reply->str);
} else {
printf("Data stored successfully\n");
}
freeReplyObject(reply);
free(json_str);
// 从 Redis 中检索数据
reply = (redisReply*)redisCommand(c, "GET team_data");
if (reply->type == REDIS_REPLY_STRING) {
Team *retrieved_team = deserialize_team(reply->str);
if (retrieved_team) {
printf("Retrieved Team Title: %s\n", retrieved_team->title);
for (int i = 0; i < retrieved_team->member_count; i++) {
printf("Member %d: Name=%s, Age=%d\n", i, retrieved_team->members[i].name, retrieved_team->members[i].age);
}
free(retrieved_team->members);
free(retrieved_team);
}
} else {
printf("Error retrieving data\n");
}
freeReplyObject(reply);
// 清理
free(team.members);
redisFree(c);
return 0;
}
5. 编译和运行
确保你已经安装了 hiredis
和 jansson
库,然后编译并运行程序。
gcc -o redis_example redis_example.c -lhiredis -ljansson
./redis_example
总结
通过将复杂结构体序列化为 JSON 字符串,可以方便地使用 Redis 存储和检索这些结构体。hiredis
库用于与 Redis 服务器进行通信,而 jansson
库用于处理 JSON 序列化和反序列化。这种方法不仅简单,而且灵活,适用于各种复杂的结构体。