zoukankan      html  css  js  c++  java
  • 缓存模式【其他模式】

    缓存模式

    public class Cache {
        /**
         * Caching Pattern【缓存模式】
         * readThrough:先尝试从缓存中读取数据,如果存在,则直接返回缓存中的数据;如果不存在,则从数据源加载,
         *              数据源中存在目标对象,则将其写入缓存,并返回加载的对象。
         * writeThrough:先将目标对象写入数据源,再将其写入缓存中
         * writeAround:先将目标对象写入数据源,则将缓存失效
         * writeBehind:如果缓存已满 && 目标对象不再缓存中,则将 LRU 对象从缓存中移除,并异步将其写入数据源中,
         *              同时将目标对象写入缓存中。
         * cacheAside:readThrough && writeAround
         */
        @Test
        public void all() {
            final CacheStore store = new CacheStore();
            final long id = 1L;
            store.writeThrough(User.of(id, "zxd"));
            final User user = store.readThrough(id);
            store.writeAround(user);
            store.readThrough(id);
            store.writeBehind(User.of(2L, "princess"));
        }
    }
    
    @Value(staticConstructor = "of")
    class User {
        private Long id;
        private String name;
    }
    
    class LruCache<K, V> extends LinkedHashMap<K, V> {
        private static final long serialVersionUID = 3409436250531011182L;
        private final int maxSize;
    
        public LruCache(int maxSize) {
            super(16, 0.75F, true);
            this.maxSize = maxSize;
        }
    
        public Entry<K, V> removeEldest() {
            final Entry<K, V> entry = entrySet().iterator().next();
            if (Optional.ofNullable(entry).isPresent()) {
                remove(entry.getKey());
            }
            return entry;
        }
    
        public boolean isfull() {
            return maxSize >= size();
        }
    }
    
    class DataSource {
        private static ConcurrentMap<Long, User> users = new ConcurrentHashMap<>();
    
        public static User load(Long id) {
            return users.get(id);
        }
    
        public static void persist(User user) {
            users.put(user.getId(), user);
        }
    
    }
    
    @Slf4j
    class CacheStore {
        LruCache<Long, User> cache = new LruCache<>(1);
    
        public User readThrough(Long id) {
            User user;
            // 1)首先尝试从缓存中读取,如果存在则直接返回
            if (Optional.ofNullable(user = cache.get(id)).isPresent()) {
                log.info("get from cache {}", user.getId());
                return user;
            }
    
            // 2)如果缓存中不存在,则从数据源读取,如果读取到值,则将其写入缓存中
            final User load = DataSource.load(id);
            Optional.ofNullable(load).ifPresent(u -> {
                log.info("load data from dataSource and set cache {}", u.getId());
                cache.put(u.getId(), u);
            });
            // 返回读取的结果
            return load;
        }
    
        public void writeThrough(User user) {
            // 1)将目标对象持久化到数据源
            DataSource.persist(user);
            // 2)将其更新到缓存中
            cache.put(user.getId(), user);
            log.info("update dataSource and set cache{}", user.getId());
        }
    
        public void writeAround(User user) {
            // 1)将目标对象持久化到数据源
            DataSource.persist(user);
            // 2)使得缓存失效【即将其从缓存中移除】
            cache.remove(user.getId());
            log.info("update dataSource and invalid cache {}", user.getId());
        }
    
        public void writeBehind(User user) {
            // 1)如果缓存已满 && 目标值未在缓存中 && LRU移除缓存并将其持久化到数据源中
            if (cache.isfull() && !cache.containsKey(user.getId())) {
                final Entry<Long, User> entry = cache.removeEldest();
                final User value = entry.getValue();
                log.info("async update dataSource {}", value.getId());
                // 异步将数据写入数据源
                CompletableFuture.runAsync(() -> {
                    DataSource.persist(value);
                });
            }
            // 2)将目标对象更新到缓存中
            cache.put(user.getId(), user);
        }
    
        public User readAside(Long id) {
            return readThrough(id);
        }
    
        public void writeAside(User user) {
            writeAround(user);
        }
    }
    
  • 相关阅读:
    Git 从入门到入坑
    单件模式(单例模式)
    装饰者模式
    观察者模式
    设计模式入门
    SpringBoot + Mybatis + Redis 整合入门项目
    Spring Boot 前后端交互及参数传递
    Spring Securtiy 认证流程(源码分析)
    Spring Boot 静态页面跳转
    第一条手机验证码
  • 原文地址:https://www.cnblogs.com/zhuxudong/p/10225869.html
Copyright © 2011-2022 走看看