`
gao_xianglong
  • 浏览: 467199 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

深入剖析SapphireFramework—本地缓存基本使用

阅读更多

 

 

前言

本篇博文将重点讲解关于Sapphire的各个方面,其中内容涉及到其Framework的底层实现细节及设计思想,所以建议大家仔细的阅读本篇博文。如果有不清楚或者不理解的地方,笔者希望大家能够通过邮件或者留言的方式告知笔者,笔者将耐心并负责的对其进行回复。

 

当然在正式开始之前,你首先需要明白的是Sapphire究竟是出于领域模型中的哪一层?以及Sapphire的目的什么?其实Sapphire作用于缓存层,其目的为分布式内存对象缓存系统。这时你可能会问笔者为什么要选用Sapphire作为你的缓存框架?市面上不是有诸多优秀的第三方开源缓存框架吗?Sapphire具备何种优势?其实谈到第三方缓存框架笔者首推EhCache,因为不论是在本地缓存领域还是在分布式缓存领域,吞吐性或者并发性方面,EhCache都是无可挑剔的,但Ehcache与生俱来的缺陷同样也不可避免。首先EhCache并不支持对缓存元素的内存管理,这一点在企业级的项目中其实是至关重要的。并且EhCache仅仅只是指针对缓存元素的数量做了管理,这只是一个“伪内存”管理。Sapphire提供真正意义上内存管理的实现,这便是你选用Sapphire的条件之1,其2,EhCache的分布式缓存不论在配置上还是使用上都显得不方便,至少对于笔者来说,更倾向简洁的配置风格,这便是你选用Sapphire的理由之2。其3,Ehcache原生并不支持Annotation,Sapphire原生则支持,这便是你选用Sapphire的理由之3。最后Sapphire提供有更加丰富和灵活的缓存回收策略缓存内存单位设置也将是你选用Sapphire的重要理由。

 

Sapphire的优点如下:

1、敏捷快速;

2、体系结构中立,跨平台支持;

3、多种缓存管理容器实现;

4、多种缓存回收策略(LRU、LFU、FIFO、RDM);

5、支持缓存注解服务驱动(Annotation方式直接缓存方法);

6、支持缓存持久化及加载虚拟机运行期数据;

7、单个缓存最大缓存容量为1gByte;

8、支持缓存容量单位设置(byte、kByte、mByte、gByte);

9、支持TCP单播集群(BIO/NIO)、P2P广播、组播集群、RMI组播集群;

10、支持与Spring的无缝集成,及事物集成;

 

一、Sapphire的下载与安装

Sapphire目前的最新版本为2.0.3.RC1,笔者本章博文所有的程序示例都将选用此版本作为其实现。好了,废话不多说,首先你可以访问Sapphire的官方地址:http://code.google.com/p/sapphire-cache/downloads/list进行对应版本的下载。

 

下载页面:

 

当你成功下载好后,你可以对于压缩包进行解压,该压缩包中包含了咱们需要使用到的依赖库、API、使用范例等资源。

至于Sapphire的安装也是极其简单的。如果你是使用Maven来管理你的项目,你可能需要先将构件下载至本地,然后上传至你的Nexus私服中,最后配置构件下载即可。当然如果是非Maven的项目则可以将构件直接导入进工程即可使用。

 

二、Sapphire的本地缓存使用

Sapphire的本地缓存使用相对于EhCache来说,则显得更加简单方便。不过可能会有诸多开发人更关心缓存性能,三句话离不开性能。既然这样,咱们就先来看看Sapphire与EhCache在本地缓存方面的缓存吞吐性测试对比

下述为Sapphire开启内存管理时与EhCache的本地缓存吞吐性操作对比:

 

通过上图我们可以发现,本地缓存的10W次吞吐性,Sapphire所花周期为1125ms,EhCache也仅仅只花了惊人的110ms。这是什么原因导致差距如此明显呢?还记得笔者在开始之前曾经给大家提到过Sapphire的缓存内存管理将是一大亮点,正式由于缓存内存的管理需要牺牲掉Sapphire的一部分性能,因为Sapphire在添加缓存元素使,底层实现需要不停的跟踪对象内存开销,以及计算对象内存开销

注意看Sapphire的Cache.java实现:

/* 序列化当前缓存对象 */
ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
new ObjectOutputStream(byteArray).writeObject(value);

/* 获取当前缓存对象容量 */
long objectInMemory = byteArray.toByteArray().length;

/* 存储当前缓存对象容量 */
cacheInMemoryList.put(key, objectInMemory);

/* 计算当前缓存已用缓存容量 */
cacheInMemory += objectInMemory;
surplusCacheInMemory = cacheInMemory < maxCacheInMemory ? maxCacheInMemory
- cacheInMemory: -1L;

  

假设笔者将上述代码实现进行注释后,咱们再来看看重新执行本地缓存的10W次吞吐性测试,看看会不会有什么改变?

下述为Sapphire关闭内存管理时与EhCache的本地缓存吞吐性操作对比:

 

值得庆幸的是,当咱们关闭Sapphire的内存管理后,Sapphire的本地缓存性能提升了不少好,峰值达到了203ms,距离EhCache仅仅只差一倍左右,当然既然目前存在一定的差距,笔者希望Sapphire在今后的道路上更够优化的更好。

 

说了这么多,来点实在的吧。打开你的IDE工具,咱们来编写第一个基于Sapphire的程序。在开始编写程序之前,咱们首先需要将Sapphire的配置文件导入进项目,配置文件存放于src下即可。

配置文件内容:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sapphire PUBLIC 
	"-//Sapphire Cache//DTD Sapphire Configuration 2.0//CN"
	"http://sapphire-cache.googlecode.com/files/sapphire-cache-2.0.3.dtd">
<sapphire>
	<!-- 缓存注解服务驱动 -->
	<service:annotation-driven auto="true" />

	<!-- 缓存持久化全局配置 -->
	<diskStore path="java.io.tmpdir" diskEternal="false"
		timeToRemoveSeconds="60" />

	<!-- 缺省缓存配置 -->
	<cache eternal="false" maxElementsInSize="100" maxCacheInMemory="1"
		capacityUnit="mByte" overflowToDisk="true" diskPersistent="false"
		timeToLiveSeconds="60" cacheCleanupPolicy="FIFO" />
</sapphire> 

 

 上述配置文件中<service:annotation-driven/>标签定义了Sapphire的注解驱动,如果你在项目中需要使用到缓存服务,那么你需要将该服务进行开启

<diskStore/>标签定义了缓存的持久化全局配置,也就是说缓存的固化配置。其中“path”属性定义了缓存固化的具体位置,“java.io.tmpdir”代表的是操作系统的临时目录,不同的操作系统其临时目录则不为相同。“diskEternal”属性定义了缓存固化是否永久有效,如果缓存固化永久有效将不执行缓存固化回收,否则执行“timeToRemoveSeconds”属性。

<cache>属性则定义了缓存的基本参数信息,其中“eternal”属性定义了缓存是否永久有效,“maxElementsInSize”属性定义了缓存的最大元素个数,“maxCacheInMemory”属性定义了缓存的最大内存资源,“capacityUnit”属性定义了内存资源单位,“overflowToDisk”属性定义了缓存是否允许持久化,“diskPersistent”属性定义了是否允许加载虚拟机重期数据,“timeToLiveSeconds”属性定义了缓存对象的回收周期,“cacheCleanupPolicy”属性定义了缓存的内存回收策略

当然如果你将“eternal”属性定义为“true”后,缓存的内存回收将失效,并且如果缓存内存溢出,这里提出的缓存溢出可能包含2个方面,第一个为缓存元素溢出,另一个为缓存内存溢出时,如果“overflowToDisk”属性设置为“false”时将Sapphire将会抛出内存溢出异常

Sapphire的缺省缓存为“defaultCache”,在配置文件中你也可以定义自定义缓存,但Sapphire不允许定义在配置文件中的缓存名称重复,否则Sapphire在初始化缓存容器时会抛出:org.sapphireframework.cache.exception.CacheNameException: Cache name not allowed to repeat异常。

 

编写第一个基于Sapphire的程序:

/* 初始化缓存管理容器 */
cacheManager = new SapphireCacheManager();
		
/* 获取缓存实例 */
Cache cache = cacheManager.getCache("defaultCache");
		
/* 缓存操作 */
cache.put("key1", "value");
cache.put("key2", 10);
cache.put("key3", 1.1D);
cache.put("key4", true);
cache.put("key5", 'A');
cache.put("key6", new CacheTest.Test_());
System.out.println(cache.get("key1"));

 

在您的程序中使用Sapphire来帮助您搭建缓存架构是一件极其简单且轻松的事情。首先我们只需初始化Sapphire缓存管理容器(上述程序示例中使用到的Sapphire管理容器为SapphireCacheManager),该容器会负责初始化一系列的缓存前期准备工作。紧接着我们需要通过SapphireCacheManager的getCache(String cacheName)方法取得缓存实例并得到一个具体的Cache对象,最后通过Cache对象的put(Object key, Object value)方法添加您所需缓存的数据即可。

至于其他的缓存CRUD操作将与ConcurrentHashMap保持一致,换句话说Sapphire就是对ConcurrentHashMap进行了轻量级封装 

SapphireCache的缺省缓存为“defaultCache”,当然你也可以在配置文件中添加你自己的自定义缓存,不过如果getCache()找不到你所定义的缓存名称时将会抛出:org.sapphireframework.cache.exception.CacheException: Unable to find the cache instances: defausltCache异常。

 

CacheManager为Sapphire的顶层缓存管理容器,其派生类有:

 

通过上图我们可以发现CacheManager的缓存容器实现为SapphireCacheManager与CacheManagerForSafety。其中SapphireCacheManager为非线程安全,而CacheManagerForSafety则基于线程安全模型就性能比较而言SapphireCacheManager显得更为高效,CacheManagerForSafety则更为安全,当然您可以根据您的具体需求选择合适您的缓存管理实现。

CacheManager提供的常用方法如下:

/**
 *	获取缓存实例
 *
* 	@author JohnGao
 * 
* 	@param String: 缓存实例名称
* 
* 	@throws Exception
* 
* 	@return Cache: 指定缓存实例
*/
public Cache getCache(String cacheName) throws Exception;
	
/**
*	获取所有缓存已用缓存内存容量
*
* 	@author JohnGao
* 
* 	@param String: 缓存实例名称
* 
* 	@throws Exception
* 
* 	@return long:所有缓存容量大小
*/
public long getCacheInMemoryAll() throws Exception;

 

当然不管您是使用任何一种缓存管理容器,Sapphire都为您提供有2种构造实现。假设您在项目中使用SapphireCacheManager作为缓存管理实现,您可以根据您具体的配置需求来达到满足您具体的实现。通常情况下,我们建议您使用缺省构造,因为这样不仅仅可以为您减少一定的代码量,且显得更为直观,但使用带参构造则会使您的应用更为灵活和高效。

使用SapphireCacheManager作为管理容器2种实现:

/* 第一种初始化Sapphire容器方式 */ 
CacheManager cacheManager = new SapphireCacheManager(); 
 或者: 
 /* 第二种初始化Sapphire容器方式 */ 
CacheManager cacheManager = new SapphireCacheManager("sapphire-cache.xml");

 

 使用CacheManagerForSafety作为管理容器2种实现:

/* 第一种初始化Sapphire容器方式 */ 
CacheManager cacheManager = new CacheManagerForSafety();  
或者: 
 /* 第二种初始化Sapphire容器方式 */ 
CacheManager cacheManager = new CacheManagerForSafety("sapphire-cache.xml");

 

注意:

如果使用第一种缓存构造实现,Sapphire的缓存管理容器会自动在根目录查找名为sapphire-cache.xml的缓存配置文件。

 

1
0
分享到:
评论

相关推荐

    本地缓存与分布式缓存优缺点,使用

    本地缓存与分布式缓存优缺点、使用场景 缓存是计算机系统中的一种优化技术,通过将频繁访问的数据存储在内存中,以减少对外部存储设备的访问次数,提高系统的响应速度和性能。本文将详细介绍本地缓存与分布式缓存的...

    Java利用ConcurrentHashMap实现本地缓存demo

    Java利用ConcurrentHashMap实现本地缓存demo;...基本功能有缓存有效期、缓存最大数、缓存存入记录、清理线程、过期算法删除缓存、LRU算法删除、获取缓存值等功能。 复制到本地项目的时候,记得改包路径哦~

    redis本地缓存与redis缓存

    在“redis本地缓存与redis缓存”的主题中,我们将深入探讨这两种缓存方式及其各自的特点。 首先,我们要理解什么是本地缓存。本地缓存指的是将数据存储在应用程序的内存中,通常是Java的HashMap、Guava Cache或C#的...

    java本地缓存ConcurrentHashMap

    java本地缓存ConcurrentHashMap

    java缓存技术深入剖析

    总结,Java缓存技术深入剖析涵盖了从基本概念到高级策略的全面内容,对于提升Java应用程序的性能和响应速度具有重要意义。通过理解并合理运用这些技术,开发者可以有效地减轻数据库压力,提高系统的整体效率。

    带有本地缓存机制的http连接框架

    1. 数据缓存策略:常见的缓存策略包括“先查缓存再请求”(Cache-first)、“先请求再缓存”(Network-first)以及“在网络不可用时使用缓存”(Cache-only)。选择哪种策略取决于应用的需求,比如对于实时性要求不...

    android本地缓存

    本篇文章将详细介绍Android本地缓存的基本概念、实现方式,以及如何使用`AsimpleCacheDemo`进行实践。 **本地缓存的基本概念** 本地缓存可以分为内存缓存和磁盘缓存。内存缓存通常使用`WeakReference`或`...

    springboot本地缓存(guava与caffeine).docx

    在本地缓存中,我们可以使用 Guava 或 Caffeine 等库来实现缓存机制。 1. 场景描述 在实际开发中,我们经常遇到需要频繁访问数据库或远程服务以获取数据的情况,这种情况下,使用本地缓存可以大大提高应用程序的...

    tianditu.js 天地图本地缓存4.0下载

    tianditu.js 天地图本地缓存4.0下载

    MAC版本outlook本地缓存路径

    为了提高应用的响应速度以及在离线状态下也能访问重要的数据,Outlook for Mac 使用了本地缓存机制。当用户首次启动Outlook for Mac 并连接到其邮箱时,该应用会自动将用户的邮件、日历、联系人等数据下载并存储到...

    ReactNative网路及本地缓存

    在这个“ReactNative网路及本地缓存”的主题中,我们将深入探讨如何在ReactNative应用中处理网络请求以及本地数据存储。 首先,我们来看网络请求部分,主要涉及Fetch API的使用。Fetch是一个现代的、基于Promise的...

    uni-app用sqlite数据库本地缓存

    使用sqlite数据库本地缓存

    浏览器缓存机制介绍与缓存策略剖析.pptx

    浏览器缓存机制介绍与缓存策略剖析 浏览器缓存机制是指浏览器在请求资源时,对已经请求过的资源进行缓存,以便下次请求时可以直接从缓存中获取,从而提高页面加载速度和减少服务器的压力。本文将详细介绍浏览器缓存...

    延时加载+静态资源本地缓存

    在现代Web应用开发中,优化用户体验和提升性能是至关重要的任务。"延时加载+静态资源本地缓存"是两...在提供的压缩包文件"静态资源本地缓存和延时加载"中,应该包含了具体的代码示例和实现细节,供读者深入学习和实践。

    Glide如何访问已经下载到本地的缓存文件(图片地址若过期自己选别的)

    研究这些文件可以帮助更深入地理解如何自定义Glide的缓存行为,以及如何访问本地缓存的图片文件。 总之,通过对Glide的缓存策略进行定制,我们可以使用图片URL的MD5值来定位本地缓存的图片,这样即使原始URL发生...

    JAVA缓存研究之剖析Jive的缓存机制

    JAVA缓存研究之剖析Jive的缓存机制JAVA缓存研究之剖析Jive的缓存机制

    iscsi本地缓存(支持多盘符)

    **ISCSI本地缓存技术详解** ISCSI(Internet Small Computer System Interface)是一种基于TCP/IP协议的存储网络协议,它允许网络设备通过IP网络传输SCSI命令,实现存储设备的远程访问。ISCSI本地缓存技术是针对...

    spring简单的缓存

    本示例将聚焦于“Spring简单的缓存”实现,帮助开发者了解如何在Spring框架中集成和使用缓存功能。 Spring框架提供了强大的缓存抽象,支持多种缓存机制,如 EhCache、Redis、Hazelcast 和 Infinispan 等。在Spring...

Global site tag (gtag.js) - Google Analytics