分頁緩存預加載算法


 

分頁緩存預加載算法:
     將數據分頁(塊)存儲在緩存,這個頁(塊),一般大於應用實際請求的頁面大小,分頁(塊)緩存的加載采取預加載方式,即在應用分頁請求還沒讀到分頁(塊)的最后一頁數據時,即預先加載下一頁的緩存。這樣做有點如下:(1)減少DB讀取次數。(2)減少緩存傳輸數據大小。(3)預加載分頁緩存則避免應用請求超時。
令:
total : 記錄總數
cm :緩存大小,每一次緩存的記錄條數
cp :當前緩存頁數
n :一次請求多少條數
p :當前請求第幾頁
x :提前幾頁開始預加載緩存
bucket:緩存第幾頁(塊)
begin : 從緩存的第幾條開始取
threshold : 觸發讀取DB條件。
令:cm >= n+ n*x  保證緩存數據可供至少請求一次才觸發預加載
則:
bucket = (p * n) / cm + 1
begin = (p - 1) * n  + 1
threshold :((p * n) % cm + n * x) >= cm
算法描述:
  1. 初始化加載緩存,從DB中取cm條記錄存入緩存。
  2. 應用分頁請求時,如果:
    1. (p * n) % cm >= n,在第(p * n) / cm + 1頁緩存從((p - 1) * n ) % cm + 1 條開始取n條記錄返回
    2. (p * n) % cm < n , 請求跨了兩個(頁)緩存,需要在兩個緩存中各取一部分數據拼接返回。在緩存從 (p * n) / cm 頁緩存中從  ((p - 1)*n - 1) % cm + 1條開始取 n - (p * n) % cm 條加上,在緩存從(p * n) / cm + 1頁緩存中從第1條開始取(p * n) % cm條合並返回。
    3. 如果 (p * n) % cm + n * x  >= cm ,觸發預加載,即從DB中加載cm條記錄至緩存。
  3. 結束。

算法demo:

package com.xx.lt;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by Jenkin.K on 17/6/1.
 */
public class PageCache {
    Map<Integer,Cache> cacheMemory = new HashMap<Integer, Cache>();
    Map<Integer, Record> dbData;
    int cm = 50;        //緩存大小
    int bucket ;        //當前緩存頁
    int begin ;         //從緩存的第幾條開始取
    int n ;             //一次請求多少條
    int p ;             //當前請求第幾頁
    int x = 2;          //提前

    public static void main(String args[]){
        PageCache pageCache = new PageCache();
        pageCache.dbData = pageCache.initData();
        pageCache.cacheMemory.put(1, pageCache.loadCache(pageCache.cm, 1));
        int total = 1000;
        int pageSize = 6;
        for(int i = 0; i < total/pageSize - 1; i++) {
            System.out.println("get "+ (i+1) +" page :" );
            pageCache.getPage(i + 1, pageSize);
        }
        System.out.println(pageCache.cacheMemory);
    }

    private Map<Integer, Record> initData(){
        Map<Integer, Record> data = new HashMap<Integer, Record>();
        for(int i = 0; i < 1000; i++){
            data.put(i+1, new Record(i+1));
        }
        return data;
    }

    public void getPage(int p, int n){
        Map<Integer, Record> page = new HashMap<Integer, Record>();
        bucket = (p * n) / cm + 1; //求當前取哪頁緩存
        begin = ((p -1) * n)  + 1;
        if((p * n) % cm > n || (p * n) % cm == n){  //沒跨緩存
            page = getFromCache(bucket, begin, n, page);
        }else {  //跨緩存
            page = getFromCache(bucket - 1, begin, n - (p * n) % cm, page);
            page = getFromCache(bucket, (bucket-1) * cm + 1, (p * n) % cm, page);
        }
        if((p * n) % cm > cm - n * x || (p * n) % cm == cm - n * x){
            System.out.println("load cache");
            cacheMemory.put(bucket + 1, loadCache(cm, bucket + 1));
        }
        System.out.println("page data : " + page);
    }

    /**
     *
     * @param bucket 第幾頁緩存
     * @param begin 從哪個開始取
     * @return
     */
    private Map<Integer, Record> getFromCache(int bucket, int begin, int n, Map<Integer, Record> page){
        Cache cache = cacheMemory.get(bucket);
        for(int i = 0; i < n; i++){
            Record r = cache.cache.get(begin + i);
            page.put(begin + i, r);
        }
        return page;
    }

    /**
     *
     * @param cm 緩存大小
     * @param bucket 第幾頁緩存
     * @return
     */
    private Cache loadCache(int cm, int bucket){
        Cache cache = new Cache();
        int deta = cm * (bucket-1) + 1;
        for(int i = 0; i < cm; i++){
            cache.cache.put(deta + i, dbData.get(deta + i));
        }
        return cache;
    }

    class Cache{
        Map<Integer, Record> cache = new HashMap<Integer, Record>();
        public String toString(){
            StringBuffer sb = new StringBuffer();
            for(Map.Entry entry : cache.entrySet()){
                sb.append(entry.getKey() + ":" + entry.getValue() + ",");
            }
            return String.valueOf(sb);
        }
    }

    class Record{
        Object value;
        Record(Object o){
            value = o;
        }
        public String toString(){
            return String.valueOf(value);
        }
    }

}

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM