关于java中的本地缓存-总结概述

转载 2016年05月30日 17:02:39

java中的本地缓存,工作后陆续用到,一直想写,一直无从下手,最近又涉及到这方面的问题了,梳理了一下。自己构造单例、guava、ehcache基本上涵盖了目前的大多数行为了。

 

为什么要有本地缓存?

在系统中,有些数据,数据量小,但是访问十分频繁(例如国家标准行政区域数据),针对这种场景,需要将数据搞到应用的本地缓存中,以提升系统的访问效率,减少无谓的数据库访问(数据库访问占用数据库连接,同时网络消耗比较大),但是有一点需要注意,就是缓存的占用空间以及缓存的失效策略。

 

为什么是本地缓存,而不是分布式的集群缓存?

         目前的数据,大多是业务无关的小数据缓存,没有必要搞分布式的集群缓存,目前涉及到订单和商品的数据,会直接走DB进行请求,再加上分布式缓存的构建,集群维护成本比较高,不太适合紧急的业务项目。

         这里介绍一下缓存使用的三个阶段(摘自info架构师文档)

          

 

本地缓存在那个区域?

         目前考虑的是占用了JVM的heap区域,再细化一点的就是heap中的old区,目前的数据量来看,都是一些小数据,加起来没有几百兆,放在heap区域最快最方便。后期如果需要放置在本地缓存的数据大的时候,可以考虑在off-heap区域,但是off-heap区域的话,需要考虑对象的序列化(因为off-heap区域存储的是二进制的数据),另外一个的话就是off-heap的GC问题。其实,如果真的数据量比较大,那其实就可以考虑搞一个集中式的缓存系统,可以是单机,也可以是集群,来承担缓存的作用。

 

搞一个单例模式,里面有个Map的变量来放置数据

关于单例模式,一个既简单又复杂的模式(http://iamzhongyong.iteye.com/blog/1539642

非常典型的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class SingletonMap {
    //一个本地的缓存Map
    private Map<String,Object> localCacheStore = new HashMap<String,Object>(); 
 
    //一个私有的对象,非懒汉模式
    private static SingletonMap singletonMap = new SingletonMap(); 
 
    //私有构造方法,外部不可以new一个对象
    private SingletonMap(){
    }  
 
    //静态方法,外部获得实例对象
    public static SingletonMap getInstance(){
        return singletonMap;
    }
 
    //获得缓存中的数据
    public Object getValueByKey(String key){
        return localCacheStore.get(key);
    }
    //向缓存中添加数据
    public void putValue(String key , Object value){
        localCacheStore.put(key, value);
    }
}

 这种能不能用?可以用,但是非常局限

1
2
3
4
5
6
7
8
但是这种的就是本地缓存了吗?答案显然不是,为啥呢?
1、  没有缓存大小的设置,无法限定缓存体的大小以及存储数据的限制(max size limit);
2、  没有缓存的失效策略(eviction policies);
3、  没有弱键引用,在内存占用吃紧的情况下,JVM是无法回收的(weak rererences keys);
4、  没有监控统计(statistics);
5、  持久性存储(persistent store);
所以,这种就直接废掉了。。。

 

引入EhCache来构建缓存(详细介绍:  http://raychase.iteye.com/blog/1545906

EhCahce的核心类:

A、CacheManager:Cache的管理类;

B、Cache:具体的cache类信息,负责缓存的get和put等操作

C、CacheConfiguration :cache的配置信息,包含策略、最大值等信息

D、Element:cache中单条缓存数据的单位

典型的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public static void main(String[] args) {
        //EhCache的缓存,是通过CacheManager来进行管理的
        CacheManager cacheManager = CacheManager.getInstance();
         
        //缓存的配置,也可以通过xml文件进行
        CacheConfiguration conf = new CacheConfiguration();
        conf.name("cache_name_default");//设置名字
        conf.maxEntriesLocalHeap(1000);//最大的缓存数量
        conf.memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LRU);//设置失效策略
         
        //创建一个缓存对象,并把设置的信息传入进去
        Cache localCache = new Cache(conf);
         
        //将缓存对象添加到管理器中
        cacheManager.addCache(localCache);
                 
        localCache.put(new Element("iamzhongyong"new Date()));
         
        System.out.println(localCache.getSize());
        System.out.println(localCache.getStatistics().toString());
        System.out.println(localCache.getName());
        System.out.println(localCache.get("iamzhongyong").toString());
        System.out.println(localCache.get("iamzhongyong").getObjectValue());   
    }

当然,Cache的配置信息,可以通过配置文件制定了。。。

优点:功能强大,有失效策略、最大数量设置等,缓存的持久化只有企业版才有,组件的缓存同步,可以通过jgroup来实现

缺点:功能强大的同时,也使其更加复杂

 

引入guava的cacheBuilder来构建缓存

这个非常强大、简单,通过一个CacheBuilder类就可以满足需求。

缺点就是如果要组件同步的话,需要自己实现这个功能。

典型的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class GuavaCacheBuilderTest {
    public static void main(String[] args) throws Exception{
        GuavaCacheBuilderTest cache = new GuavaCacheBuilderTest();
        cache.getNameLoadingCache("bixiao");
    }
    public void getNameLoadingCache(String name) throws Exception{
        LoadingCache<String, String> cache = CacheBuilder.newBuilder()       
            .maximumSize(20)//设置大小,条目数        
            .expireAfterWrite(20, TimeUnit.SECONDS)//设置失效时间,创建时间      
            .expireAfterAccess(20, TimeUnit.HOURS) //设置时效时间,最后一次被访问       
            .removalListener(new RemovalListener<String, String>() { //移除缓存的监听器
                public void onRemoval(RemovalNotification<String, String> notification) {
                    System.out.println("有缓存数据被移除了");
                }})
            .build(new CacheLoader<String, String>(){ //通过回调加载缓存
                @Override
                public String load(String name) throws Exception {
                    return name + "-" "iamzhongyong";
                }
        });
        System.out.println(cache.get(name));
        //cache.invalidateAll();
    }
}

 

缓存预热怎么搞?

A、全量预热,固定的时间段移除所有,然后再全量预热

适用场景:

1、数据更新不频繁,例如每天晚上3点更新即可的需求;

 2、数据基本没有变化,例如全国区域性数据;

B、增量预热(缓存查询,没有,则查询数据库,有则放入缓存)

适用场景:

1、  数据更新要求缓存中同步更新的场景

 

​集群内部,缓存的一致性如何保证?

如果采用ehcache的话,可以使用框架本身的JGroup来实现组内机器之间的缓存同步。

如果是采用google的cacheBuilder的话,需要自己实现缓存的同步。

A、非实时生效数据:数据的更新不会时时发生,应用启动的时候更新即可,然后定时程序定时去清理缓存;

B、需要实时生效数据:启动时可预热也可不预热,但是缓存数据变更后,集群之间需要同步

关于java中的本地缓存-总结概述

Java中的本地缓存,工作后陆续用到,一直想写,一直无从下手,最近又涉及到这方面的问题了,梳理了一下。自己构造单例、guava、ehcache基本上涵盖了目前的大多数行为了。   为什么要有本地缓...
  • fy_hanxu
  • fy_hanxu
  • 2016年05月18日 17:10
  • 511

(JAVA)Object类总结

Object类学习总结在Java中有这样一个类,它是所有类的祖先,任何类都是其子孙类,它就是java.lang.Object,如果一个类没有显式地指明其父类,那么它的父类就是Object。 Obje...
  • liufei89
  • liufei89
  • 2015年05月14日 14:53
  • 377

关于java中的本地缓存-总结概

为什么要有本地缓存? 在系统中,有些数据,数据量小,但是访问十分频繁(例如国家标准行政区域数据),针对这种场景,需要将数据搞到应用的本地缓存中,以提升系统的访问效率,减少无谓的数据库访问(数据库...
  • zbuger
  • zbuger
  • 2017年04月25日 23:03
  • 285

工作总结概述

本文档主要从我工作中涉及的4个方向(文件解析,数据库,R和Hadoop)入手。主要记录一些,别人不容易发现的问题。google能简单检索出解决方案的问题,我就不多累述,并没有太多意义。 ======...
  • yibei8811
  • yibei8811
  • 2015年10月05日 18:00
  • 297

Java输入输出流总结

题目:把字符串"1,+,2,+,3,+,4,+,5,-,6,-,7,+,8,-,9"写入D盘,并且计算字符串的值,在控制台打印。 import java.io.File; import java.io...
  • tonehao1990
  • tonehao1990
  • 2015年06月08日 22:09
  • 652

个人学习总结一Java的概述

一、了解Java         Java是完全面向对象的、安全可靠、与平台无关的编程语言。         Java的三种技术构架:JAVAEE企业版、JAVASE标准版、JAVAME小...
  • bj_lzx
  • bj_lzx
  • 2014年10月20日 17:43
  • 445

Java 数组的总结

Java数组 一.   概述 1.      定义: 数组是一种数据结构,用来存储同一类型值的集合。 2.      数组是存在下标索引的,通过下标可以获取指定位置的元素,数组小标是从0开始的,也就...
  • hua631150873
  • hua631150873
  • 2013年09月14日 21:39
  • 2066

Java 本地缓存的实现(转)

转自:http://zhangwei-david.iteye.com/blog/2179087  在java web 项目中对频繁读取且相对稳定的数据一般都是用了缓存,这样可以极大地减少数据...
  • lunhuishizhe
  • lunhuishizhe
  • 2015年01月28日 23:07
  • 2710

Web Service相关概念介绍

在上篇文章中简单对web service 进行了介绍,这篇文章将向大家介绍web service中涉及到几个常见概念。假如我现在写了一个Java实现类,假如我打算把这个实现类提供给其他类调用,最好的方...
  • heiyouhei123
  • heiyouhei123
  • 2017年05月25日 23:46
  • 222

JavaWeb之概述

胖客户端与瘦客户端        胖客户端程序指的是,当一个程序运行时需要一个单独的客户端程序支持。例如,登录QQ时,就需要一个客户端的程序运行。而瘦客户端操作时不需要进行任何其他程序的安装,直接使用...
  • u010933680
  • u010933680
  • 2013年11月17日 10:11
  • 1061
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:关于java中的本地缓存-总结概述
举报原因:
原因补充:

(最多只允许输入30个字)