分布式缓存架构:从原理到生产实践

🔥 分布式缓存架构:从原理到生产实践

文章目录

  • [🔥 分布式缓存架构:从原理到生产实践](#🔥 分布式缓存架构:从原理到生产实践)
  • [🌐 一、分布式缓存的设计动机](#🌐 一、分布式缓存的设计动机)
    • [❌ 单节点缓存的瓶颈](#❌ 单节点缓存的瓶颈)
    • [📊 缓存性能对比数据](#📊 缓存性能对比数据)
    • [✅ 分布式缓存的核心价值](#✅ 分布式缓存的核心价值)
  • [⚡ 二、缓存分片与一致性哈希](#⚡ 二、缓存分片与一致性哈希)
    • [🔄 数据分片策略](#🔄 数据分片策略)
    • [🎯 一致性哈希算法](#🎯 一致性哈希算法)
    • [🔄 客户端分片 vs 代理分片](#🔄 客户端分片 vs 代理分片)
  • [🏗️ 三、Redis Cluster 架构深度解析](#🏗️ 三、Redis Cluster 架构深度解析)
    • [🔧 Redis Cluster 核心架构](#🔧 Redis Cluster 核心架构)
    • [🎯 哈希槽(Hash Slot)分配机制](#🎯 哈希槽(Hash Slot)分配机制)
    • [⚡ 故障转移与高可用](#⚡ 故障转移与高可用)
    • [🔄 集群扩缩容操作](#🔄 集群扩缩容操作)
  • [🔄 四、Memcached 分布式方案](#🔄 四、Memcached 分布式方案)
    • [🏗️ Memcached 架构特点](#🏗️ Memcached 架构特点)
    • [⚡ Memcached 使用示例](#⚡ Memcached 使用示例)
    • [📊 Memcached 高级特性](#📊 Memcached 高级特性)
  • [⚖️ 五、架构选型与性能优化](#⚖️ 五、架构选型与性能优化)
    • [📊 Redis Cluster vs Memcached 对比](#📊 Redis Cluster vs Memcached 对比)
    • [🎯 适用场景分析](#🎯 适用场景分析)
    • [🔧 性能优化策略](#🔧 性能优化策略)

🌐 一、分布式缓存的设计动机

❌ 单节点缓存的瓶颈

​​单机Redis的局限性​​:

java 复制代码
// 单节点缓存使用示例
@Component
public class SingleNodeCacheService {
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    public Product getProduct(Long productId) {
        String cacheKey = "product:" + productId;
        
        // 1. 先查缓存
        Product product = (Product) redisTemplate.opsForValue().get(cacheKey);
        if (product != null) {
            return product;
        }
        
        // 2. 缓存未命中,查询数据库
        product = productRepository.findById(productId);
        if (product != null) {
            // 3. 写入缓存(单节点容量有限!)
            redisTemplate.opsForValue().set(cacheKey, product, Duration.ofHours(1));
        }
        
        return product;
    }
}

单节点缓存的问题分析​​:

  • 容量限制:单机内存有限,无法存储海量数据
  • 性能瓶颈:所有请求集中到一个节点,网络带宽和CPU成为瓶颈
  • 单点故障​​:节点宕机导致缓存服务完全不可用
  • 扩展困难​​:垂直扩展成本高,水平扩展复杂

📊 缓存性能对比数据

​​不同存储介质性能对比​​:

存储类型 读写延迟 QPS(吞吐能力) 容量级别 成本 典型适用场景
🧠 CPU 缓存(L1/L2/L3) 1~10 ns 数亿级 KB 级 💰💰💰 高 计算指令与寄存器数据加速
🪣 内存缓存(RAM / Redis) ~100 ns 千万级 GB 级 💰💰 中 热点数据、高频访问缓存
💾 SSD 固态存储 ~100 μs 十万级 TB 级 💰 低 温数据存储、数据库主存
🧱 机械硬盘(HDD) ~10 ms 千级 PB 级 💰 极低 冷数据归档、日志与备份

✅ 分布式缓存的核心价值

​​分布式缓存架构图​​
客户端 缓存分片1 缓存分片2 缓存分片3 缓存分片N 数据A 数据B 数据C 数据D

分布式缓存优势​​:

  • 水平扩展:通过增加节点线性提升容量和性能
  • 高可用性​​:节点故障自动转移,服务不中断
  • 负载均衡:数据分散到多个节点,避免热点
  • 故障隔离:单个节点问题不影响整体服务

⚡ 二、缓存分片与一致性哈希

🔄 数据分片策略

​​传统哈希分片的问题​​:

java 复制代码
// 简单哈希分片 - 节点变化时数据大量迁移
public class SimpleHashSharding {
    private List<String> nodes = Arrays.asList("node1", "node2", "node3");
    
    public String getNode(String key) {
        // 计算哈希值
        int hash = Math.abs(key.hashCode());
        // 取模分片
        int index = hash % nodes.size();
        return nodes.get(index);
    }
    
    // 问题:增加节点时,大部分数据需要重新分布
    public void addNode(String newNode) {
        nodes.add(newNode);
        // 80%的数据需要迁移!
    }
}

🎯 一致性哈希算法

​​一致性哈希原理​​:
数据Key 哈希环 虚拟节点1 虚拟节点2 虚拟节点3 物理节点A 物理节点B 物理节点C

​​Java实现示例​​:

java 复制代码
@Component
public class ConsistentHashSharding {
    
    // 虚拟节点数(通常160个)
    private static final int VIRTUAL_NODES = 160;
    private final TreeMap<Integer, String> hashRing = new TreeMap<>();
    
    /**
     * 添加节点到哈希环
     */
    public void addNode(String node) {
        for (int i = 0; i < VIRTUAL_NODES; i++) {
            // 为每个物理节点创建多个虚拟节点
            String virtualNode = node + "#" + i;
            int hash = getHash(virtualNode);
            hashRing.put(hash, node);
        }
    }
    
    /**
     * 根据Key获取目标节点
     */
    public String getNode(String key) {
        if (hashRing.isEmpty()) {
            return null;
        }
        
        int hash = getHash(key);
        // 找到第一个大于等于该哈希值的节点
        SortedMap<Integer, String> tailMap = hashRing.tailMap(hash);
        if (tailMap.isEmpty()) {
            // 环回第一个节点
            return hashRing.get(hashRing.firstKey());
        }
        return tailMap.get(tailMap.firstKey());
    }
    
    /**
     * 计算哈希值(使用MD5保证分布均匀)
     */
    private int getHash(String key) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] digest = md.digest(key.getBytes());
            return ((digest[3] & 0xFF) << 24) | 
                   ((digest[2] & 0xFF) << 16) | 
                   ((digest[1] & 0xFF) << 8) | 
                   (digest[0] & 0xFF);
        } catch (NoSuchAlgorithmException e) {
            return key.hashCode();
        }
    }
    
    /**
     * 测试节点变化的影响
     */
    public void testNodeChange() {
        // 初始3个节点
        addNode("node1");
        addNode("node2");
        addNode("node3");
        
        Map<String, Integer> distribution = new HashMap<>();
        for (int i = 0; i < 10000; i++) {
            String node = getNode("key" + i);
            distribution.put(node, distribution.getOrDefault(node, 0) + 1);
        }
        System.out.println("初始分布: " + distribution);
        
        // 增加一个节点
        addNode("node4");
        distribution.clear();
        for (int i = 0; i < 10000; i++) {
            String node = getNode("key" + i);
            distribution.put(node, distribution.getOrDefault(node, 0) + 1);
        }
        System.out.println("增加节点后分布: " + distribution);
    }
}

🔄 客户端分片 vs 代理分片

​​客户端分片架构​​:
应用 分片逻辑 节点1 节点2 节点3

​​客户端分片实现​​:

java 复制代码
@Component
public class ClientSideSharding {
    
    private final Map<String, RedisTemplate> nodeConnections = new HashMap<>();
    private final ConsistentHashSharding sharding;
    
    public ClientSideSharding(List<String> nodes) {
        this.sharding = new ConsistentHashSharding();
        for (String node : nodes) {
            sharding.addNode(node);
            nodeConnections.put(node, createRedisTemplate(node));
        }
    }
    
    public void set(String key, Object value) {
        String node = sharding.getNode(key);
        RedisTemplate redis = nodeConnections.get(node);
        redis.opsForValue().set(key, value);
    }
    
    public Object get(String key) {
        String node = sharding.getNode(key);
        RedisTemplate redis = nodeConnections.get(node);
        return redis.opsForValue().get(key);
    }
}

​​代理分片架构​​:
应用1 代理层 应用2 应用3 节点1 节点2 节点3

代理分片优势​​

  • 客户端透明:应用无需关心分片逻辑
  • 统一管理​​:代理层统一处理路由、故障转移
  • 协议兼容:支持多种Redis客户端
  • 运维友好:节点变化只需更新代理配置

🏗️ 三、Redis Cluster 架构深度解析

🔧 Redis Cluster 核心架构

​​Redis Cluster 拓扑结构​​:
客户端 主节点1 主节点2 主节点3 从节点1-1 从节点1-2 从节点2-1 从节点3-1

🎯 哈希槽(Hash Slot)分配机制

​​哈希槽分布原理​​:

java 复制代码
public class RedisClusterHashSlot {
    
    // Redis Cluster 固定16384个槽
    private static final int SLOT_COUNT = 16384;
    
    /**
     * 计算Key对应的哈希槽
     */
    public static int calculateSlot(String key) {
        // 只使用{}中的内容计算槽位(支持哈希标签)
        int start = key.indexOf('{');
        int end = key.indexOf('}');
        
        String slotKey = key;
        if (start != -1 && end != -1 && start < end) {
            slotKey = key.substring(start + 1, end);
        }
        
        // CRC16算法计算槽位
        int crc = CRC16.crc16(slotKey.getBytes());
        return crc % SLOT_COUNT;
    }
    
    /**
     * 哈希标签示例:相同标签的Key分配到相同槽位
     */
    public void testHashTag() {
        String key1 = "user:{1001}:profile";
        String key2 = "user:{1001}:orders";
        
        int slot1 = calculateSlot(key1); // 槽位1234
        int slot2 = calculateSlot(key2); // 槽位1234(相同!)
        
        // 这两个Key会被分配到同一个节点,支持事务和Lua脚本
    }
}

​​集群节点配置​​:

bash 复制代码
# 启动Redis集群节点
redis-server /etc/redis/7000/redis.conf --port 7000 --cluster-enabled yes
redis-server /etc/redis/7001/redis.conf --port 7001 --cluster-enabled yes

# 创建集群(3主3从)
redis-cli --cluster create \
  127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 \
  127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 \
  --cluster-replicas 1

# 查看槽位分配
redis-cli -p 7000 cluster slots

⚡ 故障转移与高可用

​​故障检测机制​​
主节点A 主节点B 主节点C 从节点A1 正常状态 定期PING PONG响应 定期PING PONG响应 主节点A故障 PING(超时) PING(超时) 标记节点A为疑似下线 确认节点A下线 发起故障转移 升级为主节点 主节点A 主节点B 主节点C 从节点A1

​​Java客户端配置​​:

java 复制代码
@Configuration
public class RedisClusterConfig {
    
    @Value("${spring.redis.cluster.nodes}")
    private String clusterNodes;
    
    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        RedisClusterConfiguration config = new RedisClusterConfiguration();
        
        // 解析集群节点配置
        String[] nodes = clusterNodes.split(",");
        for (String node : nodes) {
            String[] hostPort = node.split(":");
            config.clusterNode(hostPort[0], Integer.parseInt(hostPort[1]));
        }
        
        // 配置连接池
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxTotal(100);
        poolConfig.setMaxIdle(50);
        poolConfig.setMinIdle(10);
        poolConfig.setMaxWaitMillis(3000);
        
        return new JedisConnectionFactory(config, poolConfig);
    }
    
    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory());
        
        // 序列化配置
        Jackson2JsonRedisSerializer<Object> serializer = 
            new Jackson2JsonRedisSerializer<>(Object.class);
        template.setDefaultSerializer(serializer);
        
        return template;
    }
}

🔄 集群扩缩容操作

​​安全扩容步骤​​:

bash 复制代码
# 1. 准备新节点
redis-server /etc/redis/7006/redis.conf --port 7006 --cluster-enabled yes
redis-server /etc/redis/7007/redis.conf --port 7007 --cluster-enabled yes

# 2. 添加新节点到集群
redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7000
redis-cli --cluster add-node 127.0.0.1:7007 127.0.0.1:7000 --cluster-slave

# 3. 重新分片(迁移部分槽位)
redis-cli --cluster reshard 127.0.0.1:7000

# 4. 平衡节点槽位分布
redis-cli --cluster rebalance 127.0.0.1:7000

​​Java监控集群状态​​:

java 复制代码
@Service
public class ClusterMonitorService {
    
    @Autowired
    private RedisConnectionFactory connectionFactory;
    
    /**
     * 监控集群健康状态
     */
    public ClusterHealth checkClusterHealth() {
        ClusterHealth health = new ClusterHealth();
        
        try (RedisConnection connection = connectionFactory.getConnection()) {
            // 获取集群信息
            Properties clusterInfo = connection.info("cluster");
            health.setClusterState(clusterInfo.getProperty("cluster_state"));
            health.setSlotsAssigned(Integer.parseInt(
                clusterInfo.getProperty("cluster_slots_assigned")));
            health.setSlotsOk(Integer.parseInt(
                clusterInfo.getProperty("cluster_slots_ok")));
            
            // 检查节点状态
            List<RedisClusterNode> nodes = 
                connection.clusterGetNodes().stream()
                    .collect(Collectors.toList());
            
            health.setActiveNodes(nodes.stream()
                .filter(node -> node.isConnected() && !node.isMarkedAsFail())
                .count());
            health.setTotalNodes(nodes.size());
        }
        
        return health;
    }
    
    /**
     * 自动故障检测和告警
     */
    @Scheduled(fixedRate = 30000)
    public void autoHealthCheck() {
        ClusterHealth health = checkClusterHealth();
        
        if (!"ok".equals(health.getClusterState())) {
            alertService.sendAlert("Redis集群状态异常: " + health.getClusterState());
        }
        
        if (health.getSlotsOk() < health.getSlotsAssigned()) {
            alertService.sendAlert("Redis集群槽位异常: " + 
                health.getSlotsOk() + "/" + health.getSlotsAssigned());
        }
    }
}

🔄 四、Memcached 分布式方案

🏗️ Memcached 架构特点

​​Memcached 分布式原理​​:
客户端 一致性哈希 Memcached节点1 Memcached节点2 Memcached节点3

​​Java客户端配置​​:

java 复制代码
@Configuration
public class MemcachedConfig {
    
    @Value("${memcached.servers}")
    private String servers;
    
    @Bean
    public MemcachedClient memcachedClient() {
        try {
            // 配置连接工厂
            ConnectionFactoryBuilder builder = new ConnectionFactoryBuilder();
            builder.setOpTimeout(1000); // 操作超时1秒
            builder.setHashAlg(DefaultHashAlgorithm.KETAMA_HASH); // 一致性哈希
            builder.setLocatorType(ConnectionFactoryBuilder.Locator.CONSISTENT); // 一致性哈希定位
            
            // 创建客户端
            AuthDescriptor authDescriptor = null;
            return new MemcachedClient(builder.build(), 
                AddrUtil.getAddresses(servers));
        } catch (IOException e) {
            throw new RuntimeException("Memcached客户端初始化失败", e);
        }
    }
}

⚡ Memcached 使用示例

​​基础缓存操作​​:

java 复制代码
@Service
public class MemcachedService {
    
    @Autowired
    private MemcachedClient memcachedClient;
    
    private static final int EXPIRATION = 3600; // 1小时过期
    
    /**
     * 设置缓存
     */
    public void set(String key, Object value) {
        OperationFuture<Boolean> future = 
            memcachedClient.set(key, EXPIRATION, value);
        
        // 异步处理结果
        future.addListener(new OperationCompletionListener() {
            @Override
            public void onComplete(Operation<?> op) {
                if (!((OperationFuture<Boolean>) op).getStatus().isSuccess()) {
                    log.error("Memcached设置失败: {}", key);
                }
            }
        });
    }
    
    /**
     * 获取缓存(带本地缓存降级)
     */
    public Object get(String key) {
        try {
            // 1. 先查Memcached
            Object value = memcachedClient.get(key);
            if (value != null) {
                return value;
            }
            
            // 2. 缓存未命中,查询数据库
            value = loadFromDatabase(key);
            if (value != null) {
                // 3. 异步回填缓存
                memcachedClient.set(key, EXPIRATION, value);
            }
            
            return value;
        } catch (Exception e) {
            // 降级到本地缓存
            return localCache.get(key);
        }
    }
    
    /**
     * 批量获取(优化网络开销)
     */
    public Map<String, Object> getBulk(List<String> keys) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 批量获取减少网络往返
            Map<String, Object> cached = memcachedClient.getBulk(keys);
            result.putAll(cached);
            
            // 处理未命中的Key
            List<String> missingKeys = keys.stream()
                .filter(key -> !cached.containsKey(key))
                .collect(Collectors.toList());
            
            if (!missingKeys.isEmpty()) {
                Map<String, Object> dbData = loadFromDatabaseBulk(missingKeys);
                result.putAll(dbData);
                
                // 异步回填缓存
                for (Map.Entry<String, Object> entry : dbData.entrySet()) {
                    memcachedClient.set(entry.getKey(), EXPIRATION, entry.getValue());
                }
            }
        } catch (Exception e) {
            log.warn("Memcached批量获取失败,降级到本地缓存", e);
            // 降级处理
            for (String key : keys) {
                result.put(key, localCache.get(key));
            }
        }
        
        return result;
    }
}

📊 Memcached 高级特性

​​CAS(Check-And-Set)原子操作​​:

java 复制代码
@Service
public class MemcachedCASService {
    
    /**
     * 使用CAS实现原子计数
     */
    public long atomicIncrement(String key, long delta) {
        int maxRetries = 3;
        int retries = 0;
        
        while (retries < maxRetries) {
            try {
                // 获取当前值和CAS令牌
                GetsResponse<Long> response = 
                    (GetsResponse<Long>) memcachedClient.gets(key);
                
                if (response == null) {
                    // 键不存在,初始化
                    memcachedClient.add(key, 300, delta);
                    return delta;
                }
                
                long current = response.getValue();
                long newValue = current + delta;
                
                // CAS更新(只有值未改变时才更新)
                OperationFuture<Boolean> future = memcachedClient.cas(
                    key, response.getCas(), newValue);
                
                if (future.get()) {
                    return newValue; // 更新成功
                }
                
                retries++; // 冲突重试
                Thread.sleep(10); // 短暂等待
                
            } catch (Exception e) {
                log.error("CAS操作失败", e);
                retries++;
            }
        }
        
        throw new RuntimeException("CAS操作重试次数超限");
    }
}

⚖️ 五、架构选型与性能优化

📊 Redis Cluster vs Memcached 对比

​​详细特性对比表​​:

特性维度 Redis Cluster Memcached 优势分析
🧩 数据模型 丰富(String、Hash、List、Set、ZSet 等) 简单(Key-Value) ✅ Redis 数据结构更灵活,支持复杂业务场景
💾 持久化机制 支持 RDB / AOF / 混合持久化 ❌ 不支持 ✅ Redis 可用于缓存 + 持久化一体化方案
🔒 事务支持 支持 Lua 脚本与 MULTI/EXEC ❌ 不支持 ✅ Redis 可保证局部原子性操作
🧠 内存效率 相对较低(元数据较多) 极高(纯内存 KV) ✅ Memcached 更适合极致性能的纯缓存场景
🌐 集群能力 内置 Cluster(自动分片 + 主从复制) 客户端分片(无自动重分布) ✅ Redis 集群机制更完善
🧮 功能特性 发布订阅、Stream、BitMap、Geo 等高级功能 仅支持基础缓存 ✅ Redis 功能更强、生态更广
⚙️ 典型场景 分布式缓存、排行榜、会话管理、延时队列 静态缓存、Session 缓存、CDN 边缘加速 按业务复杂度选择合适方案

🎯 适用场景分析

​​Redis Cluster 推荐场景​​:

  • 复杂数据结构:需要Hash、List、Set等复杂操作
  • 持久化需求:缓存数据不能丢失的场景
  • 事务操作:需要原子性操作的业务
  • 实时计算:需要Redis内置的计数、排序等功能

​​Memcached 推荐场景​​:

  • ​​纯缓存场景:只需要简单的Key-Value缓存
  • 极致性能:对内存使用率和吞吐量要求极高
  • 简单架构​​:不希望引入复杂依赖
  • 大规模部署:需要数千个节点的超大规模集群

🔧 性能优化策略

​​连接池优化配置​​:

java 复制代码
@Configuration
public class OptimizedRedisConfig {
    
    @Bean
    public JedisPoolConfig jedisPoolConfig() {
        JedisPoolConfig config = new JedisPoolConfig();
        
        // 连接池大小(根据业务调整)
        config.setMaxTotal(200);          // 最大连接数
        config.setMaxIdle(50);           // 最大空闲连接
        config.setMinIdle(10);           // 最小空闲连接
        config.setMaxWaitMillis(1000);   // 获取连接超时时间
        
        // 连接有效性检查
        config.setTestOnBorrow(true);    // 获取连接时检查
        config.setTestOnReturn(true);    // 归还连接时检查
        config.setTestWhileIdle(true);   // 空闲时检查
        
        return config;
    }
    
    @Bean
    public RedisTemplate<String, Object> optimizedRedisTemplate() {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory());
        
        // 优化序列化(减少内存占用)
        StringRedisSerializer stringSerializer = new StringRedisSerializer();
        template.setKeySerializer(stringSerializer);
        template.setHashKeySerializer(stringSerializer);
        
        // 使用更高效的序列化方案
        GenericJackson2JsonRedisSerializer valueSerializer = 
            new GenericJackson2JsonRedisSerializer();
        template.setValueSerializer(valueSerializer);
        template.setHashValueSerializer(valueSerializer);
        
        return template;
    }
}

​​缓存策略优化​​:

java 复制代码
@Service
public class CacheStrategyService {
    
    /**
     * 多级缓存策略
     */
    public Object getWithMultiLevelCache(String key) {
        // 1. 本地缓存(Guava Cache)
        Object value = localCache.getIfPresent(key);
        if (value != null) {
            metrics.recordCacheHit("local");
            return value;
        }
        
        // 2. 分布式缓存(Redis)
        value = redisTemplate.opsForValue().get(key);
        if (value != null) {
            // 回填本地缓存
            localCache.put(key, value);
            metrics.recordCacheHit("redis");
            return value;
        }
        
        // 3. 数据库查询
        value = loadFromDatabase(key);
        if (value != null) {
            // 异步回填多级缓存
            CompletableFuture.runAsync(() -> {
                redisTemplate.opsForValue().set(key, value, Duration.ofHours(1));
                localCache.put(key, value);
            });
        }
        
        metrics.recordCacheMiss();
        return value;
    }
    
    /**
     * 缓存预热策略
     */
    @PostConstruct
    public void warmUpCache() {
        // 系统启动时预热热点数据
        List<String> hotKeys = identifyHotKeys();
        
        CompletableFuture.runAsync(() -> {
            for (String key : hotKeys) {
                try {
                    Object value = loadFromDatabase(key);
                    if (value != null) {
                        redisTemplate.opsForValue().set(key, value, Duration.ofHours(2));
                    }
                } catch (Exception e) {
                    log.warn("缓存预热失败: {}", key, e);
                }
            }
        });
    }
    
    /**
     * 缓存雪崩保护
     */
    public Object getWithSnowflakeProtection(String key) {
        // 1. 使用互斥锁防止缓存击穿
        String lockKey = "lock:" + key;
        if (tryLock(lockKey)) {
            try {
                Object value = redisTemplate.opsForValue().get(key);
                if (value == null) {
                    value = loadFromDatabase(key);
                    if (value != null) {
                        // 设置随机过期时间,避免同时失效
                        int expireTime = 3600 + new Random().nextInt(300); // 1小时±5分钟
                        redisTemplate.opsForValue().set(key, value, Duration.ofSeconds(expireTime));
                    }
                }
                return value;
            } finally {
                releaseLock(lockKey);
            }
        } else {
            // 等待其他线程加载缓存
            return waitForCache(key);
        }
    }
}

分布式缓存是现代应用架构的基石。选择时需要综合考虑数据模型、性能要求、运维复杂度和团队技术栈。建议从简单方案开始,随着业务复杂度提升逐步演进架构。

相关推荐
Z_z在努力3 小时前
【rabbitmq 高级特性】RabbitMQ 延迟队列全面解析
分布式·rabbitmq
_hermit:3 小时前
【从零开始java学习|第二十二篇】集合进阶之collection
java·学习
锥栗3 小时前
【Redis】【缓存】理解缓存三大问题:缓存穿透、缓存击穿与缓存雪崩及解决方案
java·后端·面试
9号达人3 小时前
泛型+函数式:让策略模式不再是复制粘贴地狱
java·后端·面试
captain3763 小时前
Java线性表
java·开发语言
tuokuac3 小时前
Java String类中的lastIndexOf方法的应用场景
java·开发语言
weixin_379880923 小时前
.Net Core WebApi集成Swagger
java·服务器·.netcore
@逆风微笑代码狗3 小时前
147.《手写实现 Promise.all 与 Promise.race》
java
文火冰糖的硅基工坊4 小时前
[嵌入式系统-98]:国内嵌入式AI算力板
人工智能·架构