缓存的设计

背景:设计一个缓存,如果在N秒内访问了M次,则为热点数据,针对热点数据,直接去访问缓存,否则去访问数据库。

设计:利用一个Map<String,Node>hotMap去维护热点的key。

其中Node的设计为:

        其中arr为当前缓存的一个数组,用于记录访问次数

        preQuery 记录上一次访问时间

        preIndex记录上一次的index。        


    static class Node {
        int[] arr;
        long preQuery;
        int preIndex;

        Node(int size) {
            arr = new int[size];
        }
    }

接口设计:

public interface SmartCache {
    String get(String key);
}

实现:

public class SmartCacheImpl implements SmartCache {

    private static final int N = 6;
    private static final int M = 5;

    private static final Map<String, Node> hotMap = new ConcurrentHashMap<>();
    private static final Map<String, String> cache = new ConcurrentHashMap<>();

    public static void main(String[] args) throws InterruptedException {
        SmartCache smartCache = new SmartCacheImpl();
        for (int i = 0; i < 10; i++) {
            Thread.sleep(500);
            smartCache.get("xy-1");
            System.out.println("-------------------------------------");
        }
        Thread.sleep(4100);
        smartCache.get("xy-1");
    }

    @Override
    public String get(String key) {
        if (isHot(key)) {
            System.out.println("热点key,从缓存中获取");
            Arrays.stream(hotMap.get(key).arr).forEach(e -> System.out.print(e + " "));
            return cache.get(key);
        }
        String value = getFromDB(key);
        cache.put(key, value);
        Arrays.stream(hotMap.get(key).arr).forEach(e -> System.out.print(e + " "));
        return value;
    }

    private String getFromDB(String key) {
        System.out.println("从数据库中去取:" + key);
        return "从数据库中去取:" + key;
    }

    private boolean isHot(String key) {
        long nao = System.currentTimeMillis() / 1000;
        System.out.println("当前访问tick:" + nao);
        int index = (int) (nao % N);
        if (hotMap.containsKey(key)) {
            Node node = hotMap.get(key);
            if (nao - node.preQuery >= N) {
                node.arr = new int[N + 1];
                node.arr[index] = 1;
                node.preQuery = nao;
                node.preIndex = index;
                System.out.println(N + "秒内无访问重置");
                return false;
            }
            node.arr[index] = node.arr[node.preIndex] + 1;

            for (int i = node.preIndex; i < index; i++) {
                node.arr[i] = node.arr[index];
            }
            node.arr[N] = node.arr[0];
            System.out.println("当前访问index:" + index + " 次数:" + (node.arr[index] - node.arr[index + 1]));
            if (node.arr[index] - node.arr[index + 1] > M) {
                node.preQuery = nao;
                node.preIndex = index;
                return true;
            }
            node.preQuery = nao;
            node.preIndex = index;
        } else {
            Node node = new Node(N + 1);
            node.arr[index] = 1;
            node.preQuery = nao;
            node.preIndex = index;
            hotMap.put(key, node);
        }
        return false;
    }

    static class Node {
        int[] arr;
        long preQuery;
        int preIndex;

        Node(int size) {
            arr = new int[size];
        }
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值