1. 程式人生 > 其它 >Mysql 主從常遇問題

Mysql 主從常遇問題

文章目錄
1、記憶體空間有限,當快取滿的時候,如何淘汰快取?
2、實現LRU demo

  • 使用Java容器LinkedHashMap
  • 雜湊表(HashMap)+雙向連結串列

1、記憶體空間有限,當快取滿的時候,如何淘汰快取?
FIFO(First In First Out)先進先出
LFU(Least Frequently Used)最不經常使用
LRU(Least Recently Used)最近最少使用

2、實現LRU demo
1、使用Java容器LinkedHashMap
LinkedHashMap本身就具有LRU演算法的特性

    class LRUCache {
        private
Map<Integer, Integer> cacheMap = null; public LRUCache(int capacity) { // 引數設定true,當removeEldestEntry()返回true,則刪除最舊的資料 cacheMap = new LinkedHashMap<Integer, Integer>(capacity,0.75F,true){ @Override protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) {
return size() > capacity; } }; } public int get(int key) { return cacheMap.getOrDefault(key, -1); } public void put(int key, int value) { cacheMap.put(key, value); } }

2、雜湊表(HashMap)+雙向連結串列
維護一個雙向連結串列,靠近連結串列尾部的結點是越早訪問的,靠近頭部的節點是最近訪問的。
如果此資料之前已經被快取在連結串列中了,我們遍歷得到這個資料對應的結點,並將其從原來的位置刪除,然後再插入到連結串列的頭部。
如果此資料沒有在快取連結串列中,又可以分為兩種情況:
如果此時快取未滿,則將此結點直接插入到連結串列的頭部
如果此時快取已滿,則連結串列尾結點刪除,將新的資料結點插入連結串列的頭部。

class LRUCache2 {
        // 當前快取容量
        private int size;
        // 限制最大快取容量
        private int capacity;
        // 定義偽頭尾節點
        private Node head;
        private Node tail;
        // 定義HashMap儲存資料
        private Map<Integer, Node> cache = new HashMap();

        // 初始化操作
        public LRUCache2(int capacity) {
            size = 0;
            this.capacity = capacity;
            // 初始化頭尾節點
            head = new Node();
            tail = new Node();
            // 讓頭尾節點相聯
            head.next = tail;
            tail.pre = head;
        }

        public int get(int key) {
            Node node = cache.get(key);
            // 不存在返回-1
            if (null == node) {
                return -1;
            }
            // 存在返回值,並且將當前節點移動到頭
            moveNodeHead(node);
            return node.value;
        }

        public void put(int key, int value) {
            Node node = cache.get(key);
            // 不存在則插入,插入後判斷當前容量是否大於限制最大容量
            if (null == node) {
                Node newNode = new Node(key, value);
                cache.put(key, newNode);
                // 放入連結串列頭部
                addNodeHead(newNode);
                size++;
                if (size > capacity) {
                    // 刪除尾結點
                    Node tail = removeNodeTail();
                    cache.remove(tail.key);
                }
            } else {
                // 存在則覆蓋value,並且將當前節點移動到頭
                node.value = value;
                moveNodeHead(node);
            }
        }

        // 放入連結串列的頭部
        private void addNodeHead(Node node) {
            // 當前頭節點的下一個節點的pre和當前節點連線
            head.next.pre = node;
            //
            node.next = head.next;
            //
            head.next = node;
            node.pre = head;
        }

        // 將節點移動到連結串列的頭部
        private void moveNodeHead(Node node) {
            node.pre.next = node.next;
            node.next.pre = node.pre;
            addNodeHead(node);
        }

        // 刪除連結串列的尾結點
        private Node removeNodeTail() {
            Node tailNode = tail.pre;
            tailNode.pre.next = tailNode.next;
            tailNode.next.pre = tailNode.pre;
            return tailNode;
        }

        // 定義一個雙向連結串列,實際的快取
        class Node {
            private int key;
            private int value;
            private Node pre;
            private Node next;
            public Node() {
            }
            public Node(int key, int value) {
                this.key = key;
                this.value = value;
            }
        }
    }