【学习】JCache简介与研究

官网: https://jcp.org/en/jsr/detail?id=107

1. 简介
JSR 107:JCache,JSR是Java Specification Requests的缩写,顾名思议就是JAVA规范第107。Jcache详细名称是Java Temporary Caching API, Java临时缓存API。
具体作用是对Java的临时缓存(比如存放在内存中)的操作进行规范,包括缓存对象的创建、共享访问、spooling(即外部设备联机并行操作)、验证以及多个JVM之间的数据同步等。

发展历程最早在2001年3月提出,经过十多年发展,在2014年3月4日通过发布审核,并定于当月18号发布稳定版本。至此,Java终于有了标准缓存规范。

J2SE 1.4在2002年发布的,JCache在2001年就提出来了,最终错过了J2EE 7(2013年发布),确实够久的。有调查显示在J2EE的问卷调查中有超过80%的开发者希望包含JCache这一技术。总而言之,它华丽的错过了。(将加入J2EE 8)。


2.用处
Cache技术在Java的生态环境中太太太常见了。常见的缓存技术如Ehcache, Hazelcast, Infinispan, GridGain, Apache Ignite, JCS…等等,以上技术在很多的系统优化解决方案中我们都见到过。最最简单的缓存技术就是将数据缓存在内存区块中,附加一些规则(如先进先出等)。而先进的缓存则可以是分布式的,跨越多台JVM、磁盘,用来操作大数据(当今流行话题之一)。

大多数缓存的解决方案是将数据存储在类似map的结构中(key-value),正因为如此,JCache API规范的标准也是基于map(类似)的结构。如果你需要高级点的用法,那到可以自己实现一些高级特征,例如JPA,但是这个规范的主要目的是希望数据在各个缓存技术之间更好的交互,以及应该在Cache方面需要升级转换到另一个技术时更加的容易,终级目的是减少开发人员的代码量。


3.  官网API研究
http://ignite.apache.org/jcache/1.0.0/javadoc/javax/cache/package-summary.html

3.1  JCache提供了五个核心接口:
  • CachingProvider: 定义了创建、配置、获取以及控制一个或多个CacheManager的方法。程序在运行过程中可以使用一个或多个CacheProvider。
  • CacheManager: 定义了创建、配置、获取以及控制一个或多个Cache。一个CacheManager从属于一个CachingProvider。
  • Cache<K, V>: 类似Map的数据结构,用来暂存数据。一个Cache从属于一个CacheManager。
  • Entry<K, V>: key-value结构的单一元素,存储在Cache里。
  • ExpiryPolicy: 一个存储在Cache中的Entry,都有存储的规则,像:会不会过期?怎么过期?这些规则统称为ExpirePolicy。

3.2  存储方式有两种:
  • 按value存(默认):当一个对象要被存到Cache里时,会拷贝后再放到Cache,读取Cache时返回的也是拷贝后的值。
  • 按Reference存:当一个对象要被存放到Cache里时,就直接按key存放了相应的值,并不会进行拷贝。这样的后果是当程序里的值改变后,相应存放在Cache里的值也会改变(不需要调用cache.put())。

3.3  一致性(Consistency)
Cache一致性是指当多个进程同时访问或操作同一个Cache时应该有的规则。所有的实现类都应该遵循JCache的默认规则(如下):
即Cache在操作时考虑在key上加锁。即读取Cache时,这时候就需要写一个lock方法锁住该key,在这个时候其它所有的操作都会被阻塞直到该锁被释放。加锁行为应该是在读操作的之前,或是在值会发生变化之前,包括在不同的JVM之间的操作。

对某些Cache的操作来说,从Cache返回的值是“最后”的那个值。这个最后的值可能是一个“老的”数据,也可能是“新的”数据,尤其是在当一个元素同时被更新时,实现类需要考虑哪个值需要被返回。

不同于以上的,其它的操作遵循的规则可能是当且仅当元素当前的状态刚好是希望的状态时,Cache值才会发生变化。在这种情况下多个线程同时操作(或更新)该Cache也是没有影响的,比如共享同一个锁。


4.  Cache<K, V>与Map区别
虽说Cache的存储数据结构与Map类似(更精确的说,应该是JCache里的Cache对象像java.util.ConncurentHashMap.),操作的API也很相似(get, put, remove等),但不同点也显而易见。
a. Cache不允许null的key或value,遇到该case时会报NPE。(从业务角度来来说,存空的键或值没有意义。对于map来说要看其具体的实现类,比如HashMap就允许空的键和值,Hashtable不允许空的键和值。)
b. Cache里的值可能会过期或收回。
c. 为了支持compare-and-swap(一种无锁算法),即比较元素的值是否发生变化,若值是一个自定义的类,那么在Cache里要重写方法Object#equals。(这是推荐的做法,并不是必须)。
d. 在Cache里,key和value在某些情况下需要实现序列化(可以进行二进制存储、传输到Cache server等)。
e. 在Cache里可能会被定义有多少的key或value可以被存储下来。
f. Cache提供安全方法的接口。

总的来说,Cache和Map是两个完全不同的东西。没啥可比性,运用场景也差很多。只能说In memery的Cache,有点类似存储在JVM里的本地Map。然后Cache的功能远不止这些,如今的发展已经是跨JVM了,形式也不仅仅是存储在内存中。


5.  JCache的实现
据官网更新(2014.09.23,有够老的),有以下实现:
a. Coherence
b. Ehcache
c. Hazelcast
d. Infinispan
e. Apache Ignite 1.0
f. Blazing Cache

而如今,大部门的Cache技术都已经支持JSR 107了。

相关网页: https://jcp.org/aboutJava/communityprocess/implementations/jsr107/index.html


6. 一个小例子,从以下例子可以了解在3.1 章节介绍的几个重要的接口的使用:
//resolve a cache manager
 CachingProvider cachingProvider = Caching.getCachingProvider();
 CacheManager cacheManager = cachingProvider.getCacheManager();

 //configure the cache
 MutableConfiguration config =
    new MutableConfiguration<>()
    .setTypes(String.class, Integer.class)
    .setExpiryPolicyFactory(AccessedExpiryPolicy.factoryOf(ONE_HOUR))
    .setStatisticsEnabled(true);

 //create the cache
 Cache cache = cacheManager.createCache("simpleCache", config);

 //cache operations
 String key = "key";
 Integer value1 = 1;
 cache.put("key", value1);
 Integer value2 = cache.get(key);
 cache.remove(key);


更多例子参见Github:
官方: https://github.com/jsr107/jsr107spec
其它: https://github.com/tomitribe/JcacheExamples


总结
我们可能对JSR-107F规范并不熟悉,但相信很多开发者都用过Cache技术,比如Ehcache, Hazelcast等等。JCache的主要作用就是定义及规范了SPI,比如过期规则、元素失效规则(LRU, FIFO等),对开发者而言正是因为这些SPI的出现,使得我们在选择具体的Cache技术时可以更好的进行切换以及降低了学习成本。存在即合理,多数Cache技术都已经支持并实现了JCache,是个好东西。


参考:
Jar包/源码下载:
http://download.oracle.com/otndocs/jcp/jcache-1_0-fr-eval-spec/index.html

JCACHE规范尘埃落定(中文):
http://www.infoq.com/cn/news/2014/04/jcache-finalized

参考文章:
https://blogs.oracle.com/theaquarium/entry/jcache_is_final_i_repeat
https://vaadin.com/blog/-/blogs/jcache-why-and-how-

J2EE相关新闻:
http://www.javaworld.com/article/2078715/enterprise-java/jcache-won-t-make-it-into-java-ee-7.html
https://dzone.com/articles/jcache-in-java-ee-8

例子:
http://grepcode.com/file/repo1.maven.org/maven2/javax.cache/cache-api/1.0.0/javax/cache/Cache.java#Cache

猜你喜欢

转载自angelbill3.iteye.com/blog/2339377