← 返回首页

分布式缓存架构:Redis集群与数据一致性

📂 java ⏱ 3 min 495 words

分布式缓存架构:Redis集群与数据一致性

概述

分布式缓存是高性能系统的关键组件。本教程介绍Redis集群、数据分片和一致性哈希。

1. Redis集群

import redis.clients.jedis.*;
import java.util.Set;

public class RedisClusterExample {
    public static void main(String[] args) {
        // 创建Redis集群连接
        Set<HostAndPort> nodes = Set.of(
            new HostAndPort("localhost", 7000),
            new HostAndPort("localhost", 7001),
            new HostAndPort("localhost", 7002)
        );
        
        JedisCluster cluster = new JedisCluster(nodes);
        
        // 操作
        cluster.set("key1", "value1");
        String value = cluster.get("key1");
        System.out.println("value: " + value);
        
        cluster.close();
    }
}

2. 一致性哈希

import java.util.*;

public class ConsistentHash<T> {
    private final TreeMap<Long, T> ring = new TreeMap<>();
    private final int virtualNodes;
    
    public ConsistentHash(int virtualNodes) {
        this.virtualNodes = virtualNodes;
    }
    
    public void addNode(T node) {
        for (int i = 0; i < virtualNodes; i++) {
            long hash = hash(node.toString() + "#" + i);
            ring.put(hash, node);
        }
    }
    
    public void removeNode(T node) {
        for (int i = 0; i < virtualNodes; i++) {
            long hash = hash(node.toString() + "#" + i);
            ring.remove(hash);
        }
    }
    
    public T getNode(String key) {
        if (ring.isEmpty()) {
            return null;
        }
        
        long hash = hash(key);
        Map.Entry<Long, T> entry = ring.ceilingEntry(hash);
        
        if (entry == null) {
            entry = ring.firstEntry();
        }
        
        return entry.getValue();
    }
    
    private long hash(String key) {
        return key.hashCode() & 0x7fffffffL;
    }
    
    public static void main(String[] args) {
        ConsistentHash<String> hash = new ConsistentHash<>(150);
        
        hash.addNode("Node1");
        hash.addNode("Node2");
        hash.addNode("Node3");
        
        for (int i = 0; i < 10; i++) {
            String key = "key" + i;
            String node = hash.getNode(key);
            System.out.println(key + " -> " + node);
        }
    }
}

3. 缓存策略

import java.util.concurrent.*;

public class CacheStrategy {
    // LRU:最近最少使用
    // LFU:最不经常使用
    // FIFO:先进先出
    // TTL:过期时间
    
    private final Map<String, CacheEntry> cache = new LinkedHashMap<>(100, 0.75f, true) {
        @Override
        protected boolean removeEldestEntry(Map.Entry<String, CacheEntry> eldest) {
            return size() > 1000;
        }
    };
    
    private static class CacheEntry {
        Object value;
        long expireTime;
        
        CacheEntry(Object value, long ttl) {
            this.value = value;
            this.expireTime = System.currentTimeMillis() + ttl;
        }
        
        boolean isExpired() {
            return System.currentTimeMillis() > expireTime;
        }
    }
    
    public void put(String key, Object value, long ttl) {
        cache.put(key, new CacheEntry(value, ttl));
    }
    
    public Object get(String key) {
        CacheEntry entry = cache.get(key);
        if (entry == null || entry.isExpired()) {
            cache.remove(key);
            return null;
        }
        return entry.value;
    }
}

4. 实际应用示例

缓存穿透防护

@Service
public class CacheService {
    private final RedisTemplate<String, Object> redisTemplate;
    
    // 布隆过滤器
    private BloomFilter<String> bloomFilter;
    
    @PostConstruct
    public void init() {
        bloomFilter = BloomFilter.create(
            Funnels.stringFunnel(Charset.defaultCharset()),
            1000000,
            0.01
        );
    }
    
    public Object getData(String key) {
        // 1. 检查布隆过滤器
        if (!bloomFilter.mightContain(key)) {
            return null;
        }
        
        // 2. 查询缓存
        Object value = redisTemplate.opsForValue().get(key);
        if (value != null) {
            return value;
        }
        
        // 3. 查询数据库
        value = database.get(key);
        if (value != null) {
            // 4. 写入缓存
            redisTemplate.opsForValue().set(key, value, 30, TimeUnit.MINUTES);
        }
        
        return value;
    }
}

缓存雪崩防护

@Service
public class CacheService {
    public Object getData(String key) {
        Object value = redisTemplate.opsForValue().get(key);
        
        if (value == null) {
            // 使用分布式锁防止缓存击穿
            String lockKey = "lock:" + key;
            try {
                if (tryLock(lockKey)) {
                    value = database.get(key);
                    if (value != null) {
                        // 随机过期时间,防止缓存雪崩
                        long ttl = 30 + ThreadLocalRandom.current().nextInt(30);
                        redisTemplate.opsForValue().set(key, value, ttl, TimeUnit.MINUTES);
                    }
                }
            } finally {
                unlock(lockKey);
            }
        }
        
        return value;
    }
}

5. 最佳实践

  1. 选择合适的缓存策略:根据业务需求选择LRU、LFU等
  2. 设置合理的过期时间:避免缓存雪崩
  3. 使用布隆过滤器:防止缓存穿透
  4. 使用分布式锁:防止缓存击穿
  5. 监控缓存命中率:优化缓存策略

总结

分布式缓存是高性能系统的关键组件。掌握Redis集群、一致性哈希和缓存策略,可以构建高效的缓存架构。