转载自:https://blog.csdn.net/u011303664/article/details/49494635
部署线上项目时被这问题折磨了一天.必须总结下
类型一:
[ERROR] [2013-08-07 @ 04:48:19] [data.data|DiskStorageFactory] Disk Write of Xdsfadfeec0des0003SQen-USQUOTE_SPEED failed (it will be evicted instead):
java.io.NotSerializableException: com.xxx.xxxx.xxxx.Aclass
跟踪代码发现,并没有显示的cache Aclass到磁盘,但为什么会有这个错呢,原因是Aclass作为Bclass的属性被引用,但代码里显示的cache了Bclass实例。从异常分析得出,Ehcache的保存磁盘机制是基于深克隆形式的,解决办法是 让Aclass implements Serializable 即可。
类型二:
[ERROR] [2013-08-07 @ 01:37:42] [performance_cache.data|DiskStorageFactory] Disk Write of getwejifd00009Hen-US failed (it will be evicted instead):
java.io.NotSerializableException: java.util.RandomAccessSubList
跟踪代码发现,alist. subList(1, alist.size()) 方法被调用了,但alist变量的真实实例是ArrayList, 它实现了RandomAccess,为什么还会报这个错了?
List alist = getSecInfoList(xx,xxx);//Suppose alist length > 1
alist. subList(1, alist.size());
原来是在getSecInfoList方法中,return的的alist是Ehcache从缓存的磁盘中取的,一旦从磁盘取出来,在用subList方法,这个错误就被抛出,解决办法是重新包装List即可:
List alist = new ArrayList(getSecInfoList(xx,xxx)); //Suppose alist length > 1
alist. subList(1, alist.size());
总结:从这两个异常来看,根本没什么技术难点,但这种错误就很容易出现,造成的结果却适得其反,原本想通过cache数据提高性能的,但实际是比不缓存性能还差。
对于类型一,如果想缓存某个javabean,请确保,它所引用的对象都implents Serializable,如果某个对象,不需要被cache,请明确的加上transient关键字。否则的话,Ehcache每次都通过引用查找的方式试着去保存所有实例数据到磁盘,但最终失败,性能肯定比不缓存还要差。
对于类型二,到是有些奇怪,通常不是很仔细的人或对Ehcache不怎么使用的来说,确实很难发现,切记就好。
Cache配置中的几个属性:
name:Cache的名称,必须是唯一的(ehcache会把这个cache放到HashMap里)。
maxElementsInMemory:内存中保持的对象数量。
maxElementsOnDisk:DiskStore中保持的对象数量,默认值为0,表示不限制。
eternal:是否是永恒数据,如果是,则它的超时设置会被忽略。
overflowToDisk:如果内存中数据数量超过maxElementsInMemory限制,是否要缓存到磁盘上。
timeToIdleSeconds:对象空闲时间,指对象在多长时间没有被访问就会失效。只对eternal为false的有效。默认值0,表示一直可以访问。
timeToLiveSeconds:对象存活时间,指对象从创建到失效所需要的时间。只对eternal为false的有效。默认值0,表示一直可以访问。
diskPersistent:是否在磁盘上持久化。指重启jvm后,数据是否有效。默认为false。
diskExpiryThreadIntervalSeconds:对象检测线程运行时间间隔。标识对象状态的线程多长时间运行一次。
diskSpoolBufferSizeMB:DiskStore使用的磁盘大小,默认值30MB。每个cache使用各自的DiskStore。
memoryStoreEvictionPolicy:如果内存中数据超过内存限制,向磁盘缓存时的策略。默认值LRU,可选FIFO、LFU。