sccache详解

刚好工作做的项目需要用到缓存技术,在网上找到很多开源的项目,最终把目光锁定到这个小而功能强大的sccache

一、sccache是什么呢
sccache是一个开源项目,SHOP.COM使用的对象缓存系统。sccache是一个in-process cache和二级、共享缓存。它将缓存对象存储到磁盘上。支持关联Key,任意大小的Key和任意大小的数据。能够自动进行垃圾收集。Sccache分为client和server,应用项目通过client把数据传递到server,或者从server提取数据。
源码地址:https://github.com/Randgalt/sccache
官方介绍与使用指南:http://code.google.com/p/sccache/
API:http://jordanzimmerman.com/sccache/

快速使用
Sccache分client和server
1、官方没有提供可用的jar文件,需要把源码下载回来,编译打成功可用的jar包
2、运行下面命令
java <jvm options> -jar shopCacheServer.jar -port <p> -path <d>
你打的jar包可能不叫shopCacheServer.jar ,参数port是server的监听端口,参数path是把数据缓存到磁盘的文件夹目录
3、创建和配置client
a、只有一个server
SCClientFactory     clientFactory = ShopComCacheFactory.getClientFactory();
SCClientContext     context = clientFactory.newContext();
context.address(new InetSocketAddress(/*address*/, /*port number*/));
SCClientManager     manager = clientFactory.newClientManager(context);

myCache = new SCCache(manager);

b、启动多台server做负载
List<SCClientManager> clientSet = new ArrayList<SCClientManager>();
SCClientFactory       clientFactory = ShopComCacheFactory.getClientFactory();

SCClientContext       context = clientFactory.newContext();
context.address(new InetSocketAddress(/*address 1*/, /*port number 1*/));
SCClientManager       manager = clientFactory.newClientManager(context);
clientSet.add(manager);

// add additional managers for each cache server

myCache = new SCCache(new SCMultiManager(clientSet));

4、编写应用调用缓存
// see if your object is in the cache
MyObject    obj = (MyObject)myCache.get(new SCDataBlock(myKey));

// if it's not, allocate it and add it to the cache
if ( obj == null )
{
    obj = new MyObject();
    myCache.put(new SCDataBlock(myKey, obj));
}


官方的步骤写了5个,其中一个说明了硬件需求,这跟实际项目需要调动就好,所以在此忽略了,如果有兴趣可以访问以下地址查看原文
https://code.google.com/p/sccache/wiki/Quickstart


3个模式
Sccache支持三种缓存模式内存、文件和序列,粗略分类其实只有两种内存和文件,通过SCDataBlock的canBeStoredInMemory、canBeStoredExternally和canBeQueued方法开启,下面详细说明三种模式。

1、内存
内存模式支持自动垃圾收集,看下面的源码了解它是怎么实现自动垃圾收集。
public void put(SCDataBlock block)
{
removeOldReferences();

fMemoryCache.put(block.getKey(), new SoftReference<SCDataBlock>(block, fQueue));
fMemoryCacheKeys.add(block.getKey());
}

把缓存的数据对象用SoftReference包装过后再存入Map(fMemoryCache)集合。SoftReference软引用对象,在响应内存需要时,由垃圾回收器决定是否清除此对象。当垃圾回收器决定把某对象回收时把引入存放到ReferenceQueue(fQueue)序列,removeOldReferences方法遍历fQueue从fMemoryCache移除。启动一条服务线程定时检查fMemoryCache缓存对象的存活时间ttl是否已经到时,若是从map中移除,而ttl的提取比较奇怪是从文件缓存管理器中查找,如果缓存对象时只开启内存模式那么该对象将在下次的检查中被移除。使用内存模式时要注意上次缓存的对象不能保证下次一定能提取到,可能由于自动垃圾收集或定时检查ttl时被移除。


2、文件
把对象序列化写入文件,读取时通过反序列化转换成可用的对象。文件缓存有两种工作模式,模式1立刻定入文件,模式2把SCDataBlock放入LinkedBlockingQueue由一条后台线程写入。读取只有一种模式即时从文件中加载,所以如果对象还在LinkedBlockingQueue还未写入文件时并不能从缓存中读取到对象。LinkedBlockingQueue初始化大小通过CCDB2Parameters的fBackgroundPutLength属性控制,当其值为0时LinkedBlockingQueue为null即不启用模式2,其默认值为1000,可通过backgroundPutLength方法进行修改。

3、序列
与文件缓存的模式2特性一样,只是该序列的控制层比文件缓存中和序列要高。


Sccache有一个bug,SCCache的close方法并不能把资源释放,看下面的原码,fIsOpen在SCCache创建时赋予布尔值为true,判断的那行代码只能会返回false,把compareAndSet参数调换即可修复问题fIsOpen.compareAndSet(true, false)。
public void               close() throws InterruptedException
     {
          if ( fIsOpen.compareAndSet(false, true) )
          {
               fPutThread.interrupt();
               fPutThread.join();
               fManager.close();
          }
     }

Sccache是key-value缓存管理,文件缓存生成两个文件分别是value和key的磁盘文件,key文件只有在SCCServer调用close方法时才会写入内容,SCStorage的open把key文件数据加载到内存。Key保存到文件之前需要做数据转换,但这过程不支持中文key,所以在再次加载key文件数据时,如果有中文key将会是乱码。

因工作需要增加sccache四点功能,有意者可以在此下载源码。
1、     完善中文key的支持。
2、     添加一个新的内存缓存方式,只有在缓存对象的ttl达到时才会移除。
3、     提供json方式序列化对象性能比原有的更高,但使用方式要复杂。
4、     实现一个新的SCClientManager子类,取消了client和server的方式,自已可完成缓存工作。

猜你喜欢

转载自xin-feng-08.iteye.com/blog/1903018