Ehcache优缺点以及分布式详解

ehcahe的介绍

EhCache 是一个纯Java的进程内缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider。Ehcache是一种广泛使用的开源Java分布式缓存。主要面向通用缓存,Java EE和轻量级容器。它具有内存和磁盘存储,缓存加载器,缓存扩展,缓存异常处理程序,一个gzip缓存servlet过滤器,支持REST和SOAP api等特点。

EhCache 应用架构图,下图是 EhCache 在应用程序中的位置:

ehcahe的优点

  1. 快速
  2. 简单
  3. 缓存数据有两级:内存和磁盘,因此无需担心容量问题
  4. 缓存数据会在虚拟机重启的过程中写入磁盘
  5. 可以通过RMI、可插入API等方式进行分布式缓存
  6. 具有缓存和缓存管理器的侦听接口
  7. 支持多缓存管理器实例,以及一个实例的多个缓存区域
  8. 提供Hibernate的缓存实现
  9. 多种缓存策略,Ehcache提供了对大数据的内存和硬盘的存储,最近版本允许多实例、保存对象高灵活性、提供LRU、LFU、FIFO淘汰算法,基础属性支持热配置、支持的插件多

ehcahe的缺点

  1. 使用磁盘Cache的时候非常占用磁盘空间:这是因为DiskCache的算法简单,该算法简单也导致Cache的效率非常高。它只是对元素直接追加存储。因此搜索元素的时候非常的快。如果使用DiskCache的,在很频繁的应用中,很快磁盘会满。
  2. 不能保证数据的安全:当突然kill掉java的时候,可能会产生冲突,EhCache的解决方法是如果文件冲突了,则重建cache。这对于Cache数据需要保存的时候可能不利。当然,Cache只是简单的加速,而不能保证数据的安全。如果想保证数据的存储安全,可以使用Bekeley DB Java Edition版本。这是个嵌入式数据库。可以确保存储安全和空间的利用率。

ehcache参数配置

https://blog.52itstyle.com/archives/439/

ehcach本地缓存配置

配置实现(ehcache-local.xml)

<?xml version="1.0" encoding="UTF-8"?>
<ehcache updateCheck="false" name="defaultCache">
    <!-- 本地缓存-->
    <diskStore path="java.io.tmpdir" />
    <!--timeToIdleSeconds=y:缓存创建以后,最后一次访问缓存的日期至失效之时的时间间隔y;timeToLiveSeconds=x:缓存自创建日期起至失效时的间隔时间x;-->
    <defaultCache maxElementsInMemory="1000" eternal="false" timeToIdleSeconds="300" timeToLiveSeconds="600"
        overflowToDisk="true" maxElementsOnDisk="10000000" />
        
    <!-- 系统缓存 -->
    <cache name="sysCache" maxElementsInMemory="1000" eternal="true" overflowToDisk="true"/>
    
    <cache name="shiro-activeSessionCache"  
           maxElementsInMemory="1000"  
           overflowToDisk="true"  
           timeToLiveSeconds="0"  
           timeToIdleSeconds="0"  
           diskPersistent="true"  
           diskExpiryThreadIntervalSeconds="600"/>  
</ehcache>

ehcahe分布式集群

EhCache的分布式缓存有传统的RMI,1.5版的JGroups,1.6版的JMS。分布式缓存主要解决集群环境中不同的服务器间的数据的同步问题。

RMI方式实现分布式缓存

方式一: RMI组播方式

ehcache-rmi.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<ehcache updateCheck="false" name="defaultCache">
    <!-- 分布式缓存RMI同步(大规模集群、复杂环境慎用) -->
    <diskStore path="java.io.tmpdir" />
        
    <cacheManagerPeerProviderFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
        properties="peerDiscovery=automatic,multicastGroupAddress=230.0.0.1, multicastGroupPort=4446" />
    <cacheManagerPeerListenerFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory" />

    <!-- 默认缓存配置. -->
    <defaultCache maxEntriesLocalHeap="100" eternal="false" timeToIdleSeconds="300" timeToLiveSeconds="600"
        overflowToDisk="true" maxEntriesLocalDisk="100000" >
        <cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
            properties="replicatePuts=false,replicateUpdatesViaCopy=false"/>
    </defaultCache>
    
    <!-- 系统缓存 -->
    <cache name="sysCache" maxEntriesLocalHeap="100" eternal="true" overflowToDisk="true">
        <cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"/>
    </cache>
    
    <!-- 系统活动会话缓存 -->
    <cache name="shiro-activeSessionCache" maxEntriesLocalHeap="10000" overflowToDisk="true"
            eternal="true" timeToLiveSeconds="0" timeToIdleSeconds="0"
            diskPersistent="true" diskExpiryThreadIntervalSeconds="600">
        <cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
            properties="replicateAsynchronously=true, replicatePuts=true, replicateUpdates=true,
                replicateUpdatesViaCopy=false, replicateRemovals=true "/>
    </cache>
        
</ehcache>

实现原理

这样当缓存改变时,ehcache会向230.0.0.1端口4446发RMI UDP组播包。

缺陷

EHCACHE的组播做得比较初级,功能只是基本实现(比如简单的一个HUB,接两台单网卡的服务器,互相之间组播同步就没问题),对一些复杂的环境(比如多台服务器,每台服务器上多地址,尤其是集群,存在一个集群地址带多个物理机,每台物理机又带多个虚拟站的子地址),就容易出现问题。

究其原因, 组播/广播转发是一个很复杂的过程. 简单的说, 一个组播缺省只能在一个网段内传输,不能跨网段。

举个简单的例子, PC机网卡的自动获取地址,还有WINDOWS里的网上邻居,都属于典型的广播服务,所以这些服务都是不能跨网段(跨路由)的,当然也不是完全不行,借助一些工具,比如CISCO路由器上的udp-broadcast helper,或者微软的netBIOS on Tcp/ip,就可以实现。

我们自己安装一些软件时,也经常遇到比如"将网卡的广播转发打开"之类的操作。

而在多网卡的主机,或同一网卡多IP的主机上,尽管地址可能是一个网段内的,但其实地址间已经存在跳数了(hop),其实就是从一个地址向另一个地址跳. 这时广播/组播就容易被阻断。

比如: 我们自己的WINDOWS上装一个VMWARE虚拟机,尽管IP地址是一个网段的,但因为虚拟机采用的桥模式不是标准的网桥模式(也可能是需要配置一下,但说实话懒得研究VMWARE了),所以广播/组播也经常出现不通的情况。

更何况在一些云计算的环境,集群的分布往往是跨网段的,甚至是跨地域的.这时更难以依赖这种初级的组播同步. 总之,分布式集群架构,建议使用Redis或者Memcache缓存实现。

方式二:p2p方式

其实就是每个节点和其他n-1个节点都建立TCP的P2P PEER。

方式三:JMS消息模式

原理:这种模式的核心就是一个消息队列,每个应用节点都订阅预先定义好的主题,同时,节点有元素更新时,也会发布更新元素到主题中去。各个应用服务器节点通过侦听MQ获取到最新的数据,然后分别更新自己的Ehcache缓存,Ehcache默认支持ActiveMQ,我们也可以通过自定义组件的方式实现类似Kafka,RabbitMQ。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏华仔的技术笔记

IPFS+IPNS+个人博客搭建

79670
来自专栏各种机器学习基础算法

nginx服务器访问时没解析PHP,直接下载php文件

在配置服务器的时候,有时候会出现这种情况,将域名映射到目录下,访问该域名却直接下载index.php文件。这种情况该如何解决呢? location ~ \.ph...

700110
来自专栏13blog.site

Maven构建项目速度太慢的解决办法

问题描述 通过idea新建maven项目,参数设置好后,idea自动构建maven项目时,速度很慢。 参数设置如图: ? 执行时间如下图: ? Total ti...

32870
来自专栏北京马哥教育

1000+人推荐的30个实用的Linux命令

本文由马哥教育Linux云计算面授班25期学员推荐,转载自互联网,作者为Mandy,内容略经小编改编和加工,观点跟作者无关,最后感谢作者的辛苦贡献与付出。 1...

337110
来自专栏淡定的博客

php之laravel学习常见错误2(连载中)

下面是我们整理的php的laravel学习的常见的错误以及解决的办法,我还会持续更新,请关注

9220
来自专栏C/C++基础

C++实现简易log日志系统

在软件开发周期中,不管是前台还是后台,系统一般会采用一个持久化的日志系统来记录运行情况。

91220
来自专栏菩提树下的杨过

gradle项目中profile的实现

gradle中并没有直接类似maven中的profile支持,只能变通的用其它方法来处理,在打包不同环境的应用时,通常会遇到二类问题: 一、不同的环境依赖的ja...

24360
来自专栏行者常至

idea Java 代码编写规范

17100
来自专栏一个会写诗的程序员的博客

Spring Boot 日志Spring Boot 日志

在任何一个生产系统中,对日志的合理记录是非常重要的。这对系统故障的定位处理极其关键。Spring Boot支持Java Util Logging,Log4j2,...

19590
来自专栏技术/开源

开源API测试工具 Hitchhiker v0.6更新 - 改进压力测试

Hitchhiker 是一款开源的支持多人协作的 Restful Api 测试工具,支持Schedule, 数据对比,压力测试,支持上传脚本定制请求,可以轻松部...

39180

扫码关注云+社区

领取腾讯云代金券