You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否使用HSET将嵌套字典以哈希结构存储在Redis中?

结论

Redis 原生哈希(Hash)结构不支持直接存储嵌套字典,其设计为单key下对应若干平级字段(field)和值(value),所有value仅支持字符串、整数、浮点数这类标量类型,无法直接存储字典、列表等复合结构,这就是你运行报错的根本原因。

替代方案(无需全局序列化整个字典)

方案1:字段路径扁平化存储

将嵌套字典的层级路径用分隔符(如冒号:、点.)拼接作为哈希的字段名,把所有嵌套结构拍平为平级键值对后存入哈希,读取时再按路径规则还原为嵌套字典即可。
示例实现代码:

from redis import StrictRedis

def flatten_dict(d, parent_key='', sep=':'):
    items = []
    for k, v in d.items():
        new_key = f"{parent_key}{sep}{k}" if parent_key else k
        if isinstance(v, dict):
            items.extend(flatten_dict(v, new_key, sep=sep).items())
        elif isinstance(v, list):
            for idx, item in enumerate(v):
                list_key = f"{new_key}{sep}{idx}"
                if isinstance(item, (dict, list)):
                    items.extend(flatten_dict(item, list_key, sep=sep).items())
                else:
                    items.append((list_key, item))
        else:
            items.append((new_key, v))
    return dict(items)

foo = {
    "host_data": {
        "hostname": "some_host",
        "mac_address": "82:fa:8e:63:40:05",
        "root_password": {
            "is_crypted": True,
            "password": "sha512_password"
        },
        "network": {
            "ip_address": "192.168.0.10/24",
            "default_gateway": "192.168.0.1",
            "vmnic": "vmnic3",
            "vlan": 20
        },
        "dns_servers": [
            "dns01.local",
            "dns02.local"
        ]
    },
    "installation_type": "esxi",
    "image_data": {
        "type": "vCenter_contentlib",
        "host": "vcenter01",
        "credential": {
            "username": "some_user",
            "password": "some_password"
        },
        "content_library": "the_content_lib_name",
        "image_name": "some_image"
    },
    "host_short_name": "esxi021"
}

redis_connection = StrictRedis(host='localhost', port=6379, charset="utf-8", decode_responses=True)
# 拍平后存入哈希
flat_foo = flatten_dict(foo)
redis_connection.hset("test", mapping=flat_foo)

# 读取单个嵌套字段示例,比如取host_data下的ip地址
print(redis_connection.hget("test", "host_data:network:ip_address"))
# 输出:192.168.0.10/24

这个方案完全基于原生Hash实现,不需要额外模块,还支持单独读写任意层级的字段,不需要加载整个字典。

方案2:使用RedisJSON模块存储

RedisJSON是Redis官方推出的JSON结构存储模块,原生支持完整的嵌套JSON结构读写,支持按路径查询、修改单个嵌套字段,性能远高于全局序列化的方案,你的Redis 6.2.5版本完全兼容RedisJSON 2.x版本。
示例实现代码:

from redis import StrictRedis

redis_connection = StrictRedis(host='localhost', port=6379, charset="utf-8", decode_responses=True)
# 直接存储整个嵌套字典
redis_connection.json().set("test_json", "$", foo)

# 单独查询嵌套字段
print(redis_connection.json().get("test_json", "$.host_data.network.ip_address"))
# 输出:['192.168.0.10/24']

# 单独修改嵌套字段
redis_connection.json().set("test_json", "$.host_data.network.vlan", 30)

这个方案是最贴合需求的实现,完全不需要处理序列化逻辑,原生支持嵌套结构操作。

方案3:局部序列化

如果既不能安装RedisJSON模块,也不想把整个结构拍平,可以仅把嵌套层级的value序列化为JSON字符串,平级字段保持原生存储:

import json
from redis import StrictRedis

redis_connection = StrictRedis(host='localhost', port=6379, charset="utf-8", decode_responses=True)
# 仅嵌套字段序列化
foo_to_save = {
    "host_data": json.dumps(foo["host_data"]),
    "image_data": json.dumps(foo["image_data"]),
    "installation_type": foo["installation_type"],
    "host_short_name": foo["host_short_name"]
}
redis_connection.hset("test", mapping=foo_to_save)

# 读取平级字段直接拿
print(redis_connection.hget("test", "installation_type"))
# 读取嵌套字段反序列化对应value即可
host_data = json.loads(redis_connection.hget("test", "host_data"))

内容的提问来源于stack exchange,提问作者AlexK

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 09:54:03