redis存储树结构的数据

redis存储树结构的数据

你理解的很对,如果节点实体数据中已经包含了父节点 ID 和子节点 ID 集合,那么你可以通过存储节点的实体数据来实现树结构的存储和操作,而不需要额外的 Redis key 来保存子节点的树结构。这样做可以简化实现,并减少数据冗余。

数据存储设计

  • 节点数据存储
    • Redis Keynode:<nodeId>
    • 数据内容:包含节点的 ID、父节点 ID、节点数据(如基础信息、模板列表)、子节点 ID 集合。

示例实现

1. 节点实体的定义

假设节点实体的定义如下:

public class Node {
    private String id;
    private String parentId;
    private Map<String, Object> data;
    private List<String> childrenIds;

    // Getters and Setters
}
2. 添加节点
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

@Service
public class TreeService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    private static final String NODE_KEY_PREFIX = "node:";

    public void addNode(Node node) {
        // 保存节点数据
        redisTemplate.opsForValue().set(NODE_KEY_PREFIX + node.getId(), node);

        if (node.getParentId() != null) {
            // 获取父节点
            Node parentNode = (Node) redisTemplate.opsForValue().get(NODE_KEY_PREFIX + node.getParentId());
            if (parentNode != null) {
                // 更新父节点的子节点集合
                parentNode.getChildrenIds().add(node.getId());
                redisTemplate.opsForValue().set(NODE_KEY_PREFIX + node.getParentId(), parentNode);
            }
        }
    }
}
3. 删除节点
public void deleteNode(String nodeId) {
    // 删除节点数据
    redisTemplate.delete(NODE_KEY_PREFIX + nodeId);

    // 获取要删除节点的父节点
    Node nodeToDelete = (Node) redisTemplate.opsForValue().get(NODE_KEY_PREFIX + nodeId);
    if (nodeToDelete != null && nodeToDelete.getParentId() != null) {
        Node parentNode = (Node) redisTemplate.opsForValue().get(NODE_KEY_PREFIX + nodeToDelete.getParentId());
        if (parentNode != null) {
            // 从父节点的子节点集合中删除该节点
            parentNode.getChildrenIds().remove(nodeId);
            redisTemplate.opsForValue().set(NODE_KEY_PREFIX + parentNode.getId(), parentNode);
        }
    }
}
4. 获取节点数据
public Node getNode(String nodeId) {
    return (Node) redisTemplate.opsForValue().get(NODE_KEY_PREFIX + nodeId);
}
5. 获取子节点数据
import java.util.ArrayList;
import java.util.List;

public List<Node> getChildrenData(String nodeId) {
    Node parentNode = getNode(nodeId);
    List<Node> childrenData = new ArrayList<>();

    if (parentNode != null) {
        List<String> childrenIds = parentNode.getChildrenIds();
        
        // 使用管道技术批量获取子节点详细数据
        redisTemplate.executePipelined((connection) -> {
            for (String childId : childrenIds) {
                connection.get((NODE_KEY_PREFIX + childId).getBytes());
            }
            return null;
        }).forEach(result -> {
            if (result != null) {
                Node childNode = deserialize(result); // 自定义方法反序列化数据
                if (childNode != null) {
                    childrenData.add(childNode);
                }
            }
        });
    }

    return childrenData;
}

private Node deserialize(Object result) {
    // 实现反序列化节点数据的逻辑
    // 例如,将 byte[] 转换为 Node 对象
    return null;
}

总结

优点

  1. 简化设计:只需一个 Redis key 存储每个节点的详细数据,不需要额外的结构来保存子节点。
  2. 直接存取:可以直接读取和写入节点数据,减少了数据结构的复杂性。

缺点

  1. 一致性维护:在节点增删改操作时,需要确保父子节点数据的一致性,特别是在并发环境下。
  2. 性能考量:如果节点数目非常多,可能需要优化数据操作和存取性能。

通过这样的设计,你可以有效地利用 Redis 来存储和操作树结构数据,同时保持数据的简洁性和高效性。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值