当前位置: 首页 > news >正文

Redis--基础知识点--27--redis缓存分类树

在 Redis 中存储分类树,通常需要选择合适的数据结构来表现层级关系。以下是使用 字符串(String)哈希(Hash) 两种常见方案的举例说明,结合电商分类场景(如 电子产品 > 手机 > 智能手机 > 品牌)展开:


方案一:字符串(String)存储路径

数据结构设计
  • 键名category:path:{node_id}
    • 例如:category:path:1001
  • :完整分类路径(用分隔符连接)
    • 例如:电子产品>手机>智能手机>苹果
操作示例
  1. 添加分类

    # 添加根节点(电子产品)
    SET category:path:1001 "电子产品"# 添加子节点(手机)
    SET category:path:1002 "电子产品>手机"# 添加叶节点(苹果)
    SET category:path:1005 "电子产品>手机>智能手机>苹果"
    
  2. 查询分类

    # 获取苹果的完整路径
    GET category:path:1005  # 返回 "电子产品>手机>智能手机>苹果"# 查询所有手机相关分类(通过模式匹配)
    KEYS category:path:1002*  # 返回匹配的键(需谨慎使用 KEYS 命令)
    
  3. 删除分类

    # 删除苹果分类(需同时处理其子节点,此处假设无子节点)
    DEL category:path:1005
    
  4. 遍历分类树

    # 查询所有根节点(假设根节点路径不含 ">")
    SCAN 0 MATCH category:path:* COUNT 100  # 遍历所有键,过滤不含 ">" 的值
    
优缺点
  • 优点:实现简单,路径直观。
  • 缺点
    • 查询子节点需解析路径字符串(如通过 STRSPLIT 拆分 >)。
    • 更新路径需级联修改所有子节点(如重命名“手机”为“移动设备”,需更新所有子节点路径)。

方案二:哈希(Hash)存储层级关系

数据结构设计
  • 键名category:node:{node_id}
  • 字段
    • name: 分类名称
    • parent_id: 父节点 ID(根节点为 0nil
    • level: 层级深度(可选)
操作示例
  1. 添加分类

    # 添加根节点(电子产品)
    HSET category:node:1001 name "电子产品" parent_id 0 level 1# 添加子节点(手机)
    HSET category:node:1002 name "手机" parent_id 1001 level 2# 添加叶节点(苹果)
    HSET category:node:1005 name "苹果" parent_id 1003 level 4
    
  2. 查询分类

    # 获取苹果的父节点 ID
    HGET category:node:1005 parent_id  # 返回 "1003"# 查询手机的所有子节点(需递归查询)
    # 步骤1:找到手机的节点ID(假设为1002)
    # 步骤2:查询所有 parent_id=1002 的节点
    SCAN 0 MATCH category:node:* COUNT 100 | xargs -I{} redis-cli HGET {} parent_id | grep 1002
    
  3. 删除分类

    # 删除苹果分类(需同时删除其子节点,此处假设无子节点)
    DEL category:node:1005
    
  4. 遍历分类树

    # 查询所有根节点(parent_id=0)
    SCAN 0 MATCH category:node:* COUNT 100 | xargs -I{} redis-cli HGET {} parent_id | grep 0
    
优缺点
  • 优点
    • 结构清晰,便于查询父子关系。
    • 修改分类名称无需级联更新子节点(仅修改当前节点 name 字段)。
  • 缺点
    • 查询子节点需递归或多次访问 Redis。
    • 需维护 parent_idlevel 字段,增加数据一致性风险。

方案三:优化方案 - 路径枚举 + 哈希

结合两种方案优点,使用 哈希存储属性 + 字符串存储路径枚举

数据结构设计
  • 哈希category:node:{node_id} 存储 nameparent_id
  • 字符串category:path:{node_id} 存储完整路径(如 电子产品>手机>苹果)。
操作示例
  1. 添加分类

    # 添加苹果分类
    HSET category:node:1005 name "苹果" parent_id 1003
    SET category:path:1005 "电子产品>手机>智能手机>苹果"
    
  2. 查询路径

    # 获取苹果的完整路径
    GET category:path:1005
    
  3. 查询子节点

    # 通过哈希查询父节点 ID,再通过路径枚举匹配子节点
    HGET category:node:1003 parent_id  # 假设1003是智能手机的节点ID
    KEYS category:path:1003*  # 匹配所有以智能手机路径开头的节点
    
优缺点
  • 优点
    • 路径查询高效(直接通过字符串匹配)。
    • 属性修改灵活(通过哈希单独更新)。
  • 缺点
    • 数据冗余(同时存储哈希和字符串)。
    • 需维护两种数据结构的一致性。

方案四:使用 RedisJSON 存储树形结构

如果 Redis 版本支持 RedisJSON 模块,可直接存储 JSON 树形结构:

数据结构设计
  • 键名category:tree
  • :JSON 对象,例如:
    {"id": 1001,"name": "电子产品","children": [{"id": 1002,"name": "手机","children": [{"id": 1003,"name": "智能手机","children": [{"id": 1004, "name": "苹果"},{"id": 1005, "name": "华为"}]}]}]
    }
    
操作示例
  1. 添加分类

    JSON.SET category:tree . '{"id":1001,"name":"电子产品","children":[{"id":1002,"name":"手机","children":[]}]}'
    
  2. 查询子节点

    JSON.GET category:tree $.children[0].children  # 返回手机分类的子节点
    
  3. 更新分类

    JSON.SET category:tree $.children[0].children[0].name '移动设备'  # 重命名手机为移动设备
    
优缺点
  • 优点
    • 结构自然,支持嵌套查询。
    • 减少数据冗余(单个键存储完整树)。
  • 缺点
    • 需 Redis 版本 ≥ 4.0 且安装 RedisJSON 模块。
    • 修改深层节点需精确 JSON 路径(如 $.children[0].children[0].name)。

总结与选型建议

方案适用场景优点缺点
字符串路径简单分类树,查询需求少实现简单,路径直观更新路径需级联修改
哈希层级需频繁查询父子关系结构清晰,修改灵活查询子节点需递归
路径枚举+哈希平衡路径查询与属性修改路径查询高效,属性修改灵活数据冗余,维护复杂
RedisJSON 树形复杂分类树,需嵌套查询结构自然,支持复杂操作依赖模块,路径操作复杂

推荐方案

  • 简单场景:使用 字符串路径哈希层级
  • 中等复杂度:使用 路径枚举+哈希
  • 复杂场景:使用 RedisJSON 树形(需确保环境支持)。

相关文章:

  • 【AI论文】用于评估和改进大型语言模型中指令跟踪的多维约束框架
  • K8S Gateway API 快速开始、胎教级教程
  • AD 区域规则(Room规则)的设置
  • Mac 环境下 JDK 版本切换全指南
  • C#中的typeof操作符与Type类型:揭秘.NET反射的基础
  • React和Vue在前端开发中, 通常选择哪一个
  • 全面指南:Xinference大模型推理框架的部署与使用
  • 6大核心记忆方法
  • datax 加密
  • Qt 安装 QtMqtt 模块
  • vue3.0的name属性插件——vite-plugin-vue-setup-extend
  • 4寸工业三防手持机PDA,助力仓储高效管理
  • Elasticsearch相关面试题
  • RHCSA 考试操作手册(基于红帽企业 Linux 8/9 版本)​
  • fpga系列 HDL : Microchip FPGA开发软件 Libero Soc 安装 license申请
  • 对心理幸福感含义的探索 | 幸福就是一切吗?
  • Android开发-使用内容组件获取通讯信息
  • 【MySQL】第四弹——表的CRUD进阶(二)数据库设计
  • 《Python星球日记》 第78天:CV 基础与图像处理
  • 2025年黑客扫段攻击激增:如何构建智能防御体系保障业务安全?
  • 外交部:国际社会广泛理解和支持中方不同意台参加世卫大会的决定
  • 3年多来俄乌要首次直接对话?能谈得拢吗?
  • 北京13日冰雹过后,已受理各险种报案近3万件
  • 女外交官郑璇已任中国驻莫桑比克大使
  • 联合国秘书长欢迎中美经贸高层会谈成果
  • 继71路之后,上海中心城区将迎来第二条中运量公交