前言
在现代应用开发中,我们无时无刻不在与'对象'打交道——用户信息、商品详情、配置项、会话数据……如何高效、清晰地在缓存或数据库中存储这些结构化数据,是每一个开发者都需要面对的课题。
你可能会想到将一个对象序列化成 JSON 字符串,然后用一个简单的 Key-Value 方式存入 Redis。这确实是一种方法,但当你只想修改对象的某一个属性(比如用户的积分)时,就不得不读取整个 JSON 字符串,反序列化成对象,修改属性,再序列化回 JSON,最后整个写回 Redis。这个过程不仅繁琐,而且在并发环境下极易引发数据覆盖问题,性能开销也相当可观。
那么,有没有一种更原生、更高效的方式来处理这种'对象'存储呢?答案是肯定的。Redis 为我们提供了一种强大的数据结构,它天生就是为了解决这类问题而生——Hash(哈希/散列)。
本文将带领你深入探索 Redis Hash 的世界,通过 C++ 语言(借助 redis-plus-plus 库)的实际代码示例,从最基础的单个字段操作,到高效的批量处理,全面掌握 Hash 的使用技巧和底层逻辑,让你在数据存储方案设计上如虎添翼。
什么是 Redis Hash?
Redis 本身是一个 Key-Value 数据库,而 Hash 类型则是在这个基础上构建的'二级'键值对集合。你可以把它想象成一个特殊的值(Value),这个值本身又是一个微型的、独立的键值对数据库。
- 外部 Key:整个 Hash 对象的唯一标识符。
- 内部 Field-Value 对:Hash 对象内部存储着多个字段(Field)和它们对应的值(Value)。
打个比方,如果说普通的 Redis Key-Value 像是一个文件柜,每个抽屉(Key)里只能放一份文件(Value)。那么,Redis Hash 就像是一个抽屉(Key),里面放了一个分门别类的文件夹,文件夹里有多个标签(Field)和对应的文件(Value)。
这种结构带来的好处是显而易见的:
- 数据组织性强:将一个对象的所有相关属性聚合在一个 Key 下,逻辑清晰,便于管理。
- 节约内存:当 Hash 内的字段数量不多时,Redis 会采用一种称为
ziplist的紧凑编码方式,相比为每个属性都创建一个独立的顶级 Key,能极大地节省内存空间。 - 操作粒度更细:可以直接对 Hash 内的单个或多个字段进行增、删、改、查,而无需操作整个对象,这大大提升了性能并降低了网络开销。
- 原子性:所有对单个字段的操作都是原子性的,保证了数据的一致性。
接下来,让我们通过代码,亲手揭开 Redis Hash 的神秘面纱。
第一章:基础 CRUD —— Hash 的核心操作
我们将从最基本的'增删改查'(CRUD - Create, Read, Update, Delete)开始,这些是构建一切复杂应用的基础。
1.1 HSET 与 HGET:单个字段的读写艺术
HSET 是向 Hash 中设置单个字段值的命令,而 HGET 则是获取单个字段的值。它们是 Hash 操作中最核心、最常用的两个命令。

让我们来详细解读一下这段代码:
void test1(sw::redis::Redis& redis) {
cout << "hash and hset" << endl;
redis.flushall();
redis.(, , );
redis.(, std::(, ));
redis.(, {
std::(, ),
std::(, )
});
vector<std::pair<string, string>> fields = {
std::(, ),
std::(, )
};
redis.(, fields.(), fields.());
result = redis.(, );
(result) {
cout << << result.() << endl;
} {
cout << << endl;
}
}






