实现concurrentHashMap与redis两级缓存

发布时间 2023-07-16 10:25:36作者: 悠然逃之

一、 实现concurrentHashMap与redis两级缓存

以下是一种使用ConcurrentHashMap和Redis实现两级缓存的示例代码:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;

import java.util.concurrent.ConcurrentHashMap;

@Service
public class TwoLevelCacheService {
    private ConcurrentHashMap<String, Object> localCache = new ConcurrentHashMap<>();
    private static final String REDIS_CACHE_PREFIX = "mycache:";

    @Autowired
    private Jedis jedis;

    @Cacheable(value = "mycache", key = "#key")
    public Object getData(String key) {
        if (localCache.containsKey(key)) {
            return localCache.get(key);
        } else {
            Object data = jedis.get(REDIS_CACHE_PREFIX + key);
            if (data != null) {
                localCache.put(key, data);
            }
            return data;
        }
    }

    @CacheEvict(value = "mycache", key = "#key")
    public void clearCache(String key) {
        localCache.remove(key);
        jedis.del(REDIS_CACHE_PREFIX + key);
    }

    // Example method for adding/updating data in cache
    public void putData(String key, Object data) {
        localCache.put(key, data);
        jedis.set(REDIS_CACHE_PREFIX + key, data.toString());
    }
}

  

在上述示例中,TwoLevelCacheService类是一个实现了两级缓存的服务类。它使用了Spring的缓存注解@Cacheable和@CacheEvict来标记方法的缓存行为。

localCache是一个ConcurrentHashMap用于实现内存级别的缓存,而jedis对象是通过Spring的依赖注入来获取的用于操作Redis。

getData方法首先在本地缓存(localCache)中查找数据,如果数据不存在,则从Redis中获取,并将其存储到本地缓存以供下次使用。

clearCache方法用于除本地缓存和Redis中的缓存数据。

putData`方法示范了如何将数据添加其中数据会被存储在本地缓存和Redis中。

请注意,以上示例仅为演示目的,并可能需要根据实际需求进行适当的修改和调整。另外,确保已正确配置和初始化Redis连接,以及已启用Spring的缓存功能。

二、 实现分布式架构concurrentHashMap与redis两级缓存

 

在分布式架构中,使用ConcurrentHashMap和Redis实现两级缓存需要考虑多个节点之间的数据一致性和并发访问问题。以下是一种基于分布式锁实现的示例代码:

import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
@Service
public class DistributedCacheService {
    private ConcurrentHashMap<String, Object> localCache = new ConcurrentHashMap<>();
    @Autowired
    private RedissonClient redissonClient;
    public Object getData(String key) {
        if (localCache.containsKey(key)) {
            return localCache.get(key);
        } else {
            Lock lock = redissonClient.get(key);
            lock.lock();
            try {
                // Double-checked locking to prevent multiple threads refreshing the cache simultaneously
                if (localCache.containsKey(key)) {
                    return localCache.get(key);
                } else {
                    // Get data from Redis
                    RBucket<Object> bucket = redissonClient.getBucket(key);
                    Object data = bucket.get();
                    if (data != null) {
                        localCache.put(key, data);
                    }
                    return data;
                }
            } finally {
                lock.unlock();
            }
        }
    }

    public void putData(String key, Object data) {
        RBucket<Object> bucket = redissonClient.getBucket(key);
        bucket.set(data);
        localCache.put(key, data);
    }

    public void evictData(String key) {
        RBucket<Object> bucket = redissonClient.getBucket(key);
        bucket.delete();
        localCache.remove(key);
    }
}

  

在上述示例中,使用了Redisson作为Redis客户端库来实现分布式锁。DistributedCacheService类使用了基于双重检查锁定模式,以确保多个节点之间的数据一致性。

在getData方法中,首先在本地缓存(localCache)中检查数据,如果数据不存在,则获取一个Redisson分布式锁并进行加锁操作。进入加锁代码块后,再次检查本地缓存是否有数据,以防止其他线程在等待锁的过程中已经加载了数据。如果本地缓存依然没有数据,则从Redis中获取数据,并将其存储到本地缓存中。最后,在退出加锁代码块之前释放分布式锁。

putData方法用于存储数据,通过Redisson的RBucket对象将数据存储到Redis中,并同时更新本地缓存。

evictData方法用于清除数据,删除Redis中对应的数据并从本地缓存中移除。

请注意,上述示例中的分布式锁实现是基于Redisson的Redis分布式锁,你也可以选择其他基于Redis的分布式锁实现方式。此外,确保已正确配置和初始化Redis连接和Redisson客户端。