如何实现一个本地缓存和分布式缓存

本地缓存可以使用 EhCache 和 Google的 Guava来实现
分布式缓存可以使用 Memcached 和 redis 来实现

在这里插入图片描述
在这里插入图片描述
EhCache的本地实现
首先添加依赖

 <dependency>
   <groupId>org.ehcache</groupId>
   <artifactId>ehcache</artifactId>
   <version>3.8.1</version>
 </dependency>

然后自定义一个EhCache的实现类


public class EhcacheExample {
    public static void main(String[] args) {
        CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder().build();
        cacheManager.init();

        Cache<String, String> myCeche = cacheManager.createCache("MYCECHE", CacheConfigurationBuilder.newCacheConfigurationBuilder(
                String.class, String.class, ResourcePoolsBuilder.heap(10)));


        Cache<String, String> myCeche2 = cacheManager.createCache("MYCECHE2", CacheConfigurationBuilder.newCacheConfigurationBuilder(
                String.class, String.class, ResourcePoolsBuilder.heap(10)));

        myCeche.put("testKey","value1");
        myCeche2.put("testKey","value2");
        String testKey = myCeche.get("testKey");
        String testKey2 = myCeche2.get("testKey");
        System.out.println("testKey = " + testKey);
        System.out.println("testKey2 = " + testKey2);
        //testKey = value1
        //testKey2 = value2
        cacheManager.close();
        // CacheManager 下 可以有多个 Cache ,每个Cache 下可以有多个 k-v
    }
}

在这里插入图片描述
使用guava 生成的缓存如下


public class GuavaCache {
    public static void main(String[] args) throws ExecutionException {
        LoadingCache<String, String> loadingCache = CacheBuilder.newBuilder()
                //并发级别设置为5
                .concurrencyLevel(5)
                // 设置过期时间为8秒钟
                .expireAfterAccess(8, TimeUnit.SECONDS)
                // 初始化的容量长度为10
                .initialCapacity(10)
                // 最大的容量长度为100
                .maximumSize(100)
                //设置统计缓存的命中率
                .recordStats()
                //设置缓存的移除通知
                .removalListener(new RemovalListener<Object, Object>() {
                    @Override
                    public void onRemoval(RemovalNotification<Object, Object> removalNotification) {
                        System.out.println(removalNotification.getKey() + " key was remove , cache is   " + removalNotification.getValue());
                    }
                })
                //指定CacheLoader 缓存不存在时 ,可自动加载缓存
                .build(new CacheLoader<String, String>() {
                    @Override
                    public String load(String key) throws Exception {
                        // 自动加载缓存业务
                        return "不存在的key : " + key;
                    }
                });
        String testGuava = "testGuava";
        loadingCache.put(testGuava,"value1");
        String resultValue = loadingCache.get(testGuava);
        System.out.println("resultValue = " + resultValue);
         resultValue = loadingCache.get(testGuava+"1");
        System.out.println("resultValue2 = " + resultValue);


        //第二种方式
        Cache<String, String> objectCache = CacheBuilder.newBuilder().maximumSize(100).build();

        objectCache.put(testGuava,"max100");
        // 取一个存在的值
        String result = objectCache.get(testGuava, new Callable<String>() {
            @Override
            public String call() throws Exception {
                //自定义返回值
                return "null";

// 执行的效果如下
// resultValue = value1
//resultValue2 = 不存在的key : testGuava1
//result = max100
//result = 不存在~~~~

如何手动实现一个本地缓存
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
附上代码

  1. 自定义一个缓存中存放的对象

@Data
@AllArgsConstructor
@NoArgsConstructor
public class MyCustomizeCache implements Comparable<MyCustomizeCache>{

    /**
     * key
     */
    private Object key;
    /**
     * Value
     */
    private Object value;
    /**
     * 上次访问时间
     */
    private long lastTime;
    /**
     * 创建时间
     */
    private long writeTime;
    /**
     *存活时间
     */
    private long expireTime;
    /**
     * 命中次数
     */
    private Integer hitCount;


    @Override
    public int compareTo(MyCustomizeCache myCustomizeCache) {
        return hitCount.compareTo(myCustomizeCache.hitCount);
    }
}
  1. 自定义一个全局的ConcurrentHashMap对象
public class MyCustomizeCacheClobal {
    public static ConcurrentHashMap<String,MyCustomizeCache> concurrentHashMap=new ConcurrentHashMap<>();
}
  1. 定义一个自动检查的定时删除任务

public class ExpireThread implements Runnable{
    @Override
    public void run() {
        while (true){
            try {
                TimeUnit.SECONDS.sleep(10);
                expireCache();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private void expireCache() {
        System.out.println("检测存储是否过期");
        for (String key : MyCustomizeCacheClobal.concurrentHashMap.keySet()) {
            MyCustomizeCache customizeCache = MyCustomizeCacheClobal.concurrentHashMap.get(key);
            long expireTime = TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - customizeCache.getWriteTime());
            if (customizeCache.getExpireTime()>expireTime) {
                continue;
            }
            //清除过期缓存
            MyCustomizeCacheClobal.concurrentHashMap.remove(key);
        }
    }
}
  1. 实现一个存放缓存和获取缓存的工具类
public class MyCacheUtil {

    /**
     * 存放key、value
     * @param key
     * @param value
     * @param expireTime
     */
    public static void put(String key, Object value, long expireTime) {

        if (StrUtil.isEmpty(key)) {
            return;
        }
        // 判断在缓存中是否存在key
        if (concurrentHashMap.containsKey(key)) {
            MyCustomizeCache customizeCache = concurrentHashMap.get(key);
            customizeCache.setValue(value);
            customizeCache.setLastTime(System.currentTimeMillis());
            customizeCache.setWriteTime(System.currentTimeMillis());
            customizeCache.setExpireTime(expireTime);
            customizeCache.setHitCount(customizeCache.getHitCount() + 1);
            return;
        }
        MyCustomizeCache customizeCache = new MyCustomizeCache();
        customizeCache.setKey(key);
        customizeCache.setValue(value);
        customizeCache.setLastTime(System.currentTimeMillis());
        customizeCache.setWriteTime(System.currentTimeMillis());
        customizeCache.setExpireTime(expireTime);
        customizeCache.setHitCount(1);
        concurrentHashMap.put(key, customizeCache);
    }


    /**
     * 根据key返回数据
     * @param key
     * @return
     */
    public static Object get(String key){
        if (StrUtil.isEmpty(key)) {
            return null;
        }
        if (ObjectUtils.isEmpty(concurrentHashMap)) {
            return null;
        }
        if (!concurrentHashMap.containsKey(key)) {
            return null;
        }
        MyCustomizeCache myCustomizeCache = concurrentHashMap.get(key);
        if (Objects.isNull(myCustomizeCache)) {
            return null;
        }
        // 惰性删除
        long duration = System.currentTimeMillis() - myCustomizeCache.getWriteTime();
        long seconds = TimeUnit.MILLISECONDS.toSeconds(duration);
        // 过期时间小于 当前时间-写入时间
        if (myCustomizeCache.getExpireTime()<=seconds) {
            concurrentHashMap.remove(key);
            return null;
        }
        myCustomizeCache.setHitCount(myCustomizeCache.getHitCount()+1);
        myCustomizeCache.setLastTime(System.currentTimeMillis());
        return myCustomizeCache.getValue();
    }
}
  1. 测试检测工具类是否生效
public class MyCacheTest {
    public static void main(String[] args) {
        String key = "test1";
        MyCacheUtil.put(key,2342134,10);
        Object test1 = MyCacheUtil.get(key);
        System.out.println("test1 = " + test1);
        Object test2 = MyCacheUtil.get(key+1);
        System.out.println("test2 = " + test2);

        // 打印结果
        //test1 = 2342134
        //test2 = null
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值