分页缓存预加载算法

 

分页缓存预加载算法:
     将数据分页(块)存储在缓存,这个页(块),一般大于应用实际请求的页面大小,分页(块)缓存的加载采取预加载方式,即在应用分页请求还没读到分页(块)的最后一页数据时,即预先加载下一页的缓存。这样做有点如下:(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);
        }
    }

}

  

 
posted @ 2017-06-01 17:58  Jenkin.K  阅读(3715)  评论(1编辑  收藏  举报