吐槽一下J2Cache

摘要  呵呵,久闻J2Cache的大名,呵呵今天有点时间看了下,介个就犹豫不决了,是踩呢还是不踩呢?踩了@红薯 会不会封我的号呀,呵呵,最后想半天,最帅的红薯心胸宽广得像大海一样,那还等啥,踩吧。 就是不知道红薯会不会给个置顶机会?不给置顶给个机械键盘也成
j2cache tiny tiny framework

目录[-]
总结一下:
附:Tiny成员会出现请客的情况:
槽点一:集成方式采用ANT

工程还是传统的工程,集成还在用的ant,当然ant来做没有什么不可以,但是作为OSC这么高大上的作者拿出的作品能不能槽点高一些?已经采用了Maven了,用Maven无法独立完成的意思么?

槽点二:提交内容的不审慎

居然把Eclipse的工程文件提交到配置库,难道不知道有N多种开发工具么?不知道Eclipse工程文件中有一些东西是与本机相关的么?这样冲突如何解决呢?难不成所有作者的工程环境全是一样的?

槽点三:文件治理不够严谨

在src/main/java中赫然有xml和properties文件存在,OMG,我们的节操还可以再低一点么?测试性的代码放在了main/java中。

槽点四:架构设计比较乱

在我看来,不管是ehcache或者redis都是缓存的一个扩展,但是这些东西都被结结实实的依赖在框架的main主干中,Hibernate只是应用缓冲的一种应用场景,但是也赫然在工程结构当中,如果把J2Cache的缓冲实现扩展N种,再把J2Cache的应用推广M种,我们就欣然看到在J2Cache当中信赖了n+m种的依赖包们,我们的使用者应该怎么办呢?要么忍受利用J2Cache时带来的N多用不着的包,要么就要辛苦的去强制不依赖这些包,而这都要拜J2Cache所赐。

槽点五:程序实现也有一些问题简单列列如下

在RedisCacheProvider这个实现类中,就有如下问题(当然,如果非说它不是个问题,我也没有办法):

private static String host;
private static int port;
private static int timeout;
private static String password;
private static int database;

 

这里声明了一堆的静态变量
结果这些变量都仅在start方法中一个里面有用到,那又变成静态变量是什么意思?

private static JedisPool pool;

 

这里定义了JedisPool是个静态变量,也就意味着只能有一个实例,也就意味着如果你要开两个独立的Redis缓冲是不可行的了,如果你想在一个工程里连接两个Redis服务器--OMG,你还是死了这条心吧,除非你重写这个类。

if(key instanceof Number)
            return region + ":I:" + key;
        else{
            Class keyClass = key.getClass();
            if(String.class.equals(keyClass) || StringBuffer.class.equals(keyClass) || StringBuilder.class.equals(keyClass))
                return region + ":S:" + key;
        }
        return region + ":O:" + key;

 这里不断的有字符串相“+”,而且还是连加........

public static void main(String[] args) {
    RedisCache cache = new RedisCache("User");
    System.out.println(cache.getKeyName("Hello"));
    System.out.println(cache.getKeyName(2));
    System.out.println(cache.getKeyName((byte)2));
    System.out.println(cache.getKeyName(2L));
}

 这里还有这个,还能再任性一点么?

public Object get(Object key) throws CacheException {
    Object obj = null;
    boolean broken = false;
    Jedis cache = RedisCacheProvider.getResource();
    try {
        if (null == key)
            return null;
        byte[] b = cache.get(getKeyName(key).getBytes());
        if(b != null)
            obj = SerializationUtils.deserialize(b);
    } catch (Exception e) {
        log.error("Error occured when get data from L2 cache", e);
        broken = true;
        if(e instanceof IOException || e instanceof NullPointerException)
            evict(key);
    } finally {
        RedisCacheProvider.returnResource(cache, broken);
    }
    return obj;
}
 
@Override
public void put(Object key, Object value) throws CacheException {
    if (value == null)
        evict(key);
    else {
        boolean broken = false;
        Jedis cache = RedisCacheProvider.getResource();
        try {
            cache.set(getKeyName(key).getBytes(), SerializationUtils.serialize(value));
        } catch (Exception e) {
            broken = true;
            throw new CacheException(e);
        } finally {
            RedisCacheProvider.returnResource(cache, broken);
        }
    }
}

 这里是啥意思?当你拿到一个Cache对象,你每次添加或返回一个缓冲的值,用的居然不一定是一个Redis实例,好吧,我知道Redis的连接池还是比较快的?还是比较快就不花时间了么?

if (value == null)
            evict(key);

  Ok,这里表示,如果设置的值是null,就把这个值干掉,

public void evict(List keys) throws CacheException {
        if(keys == null || keys.size() == 0)
            return ;
        boolean broken = false;
        Jedis cache = RedisCacheProvider.getResource();
        try {
            String[] okeys = new String[keys.size()];
            for(int i=0;i<okeys.length;i++){
                okeys[i] = getKeyName(keys.get(i));
            }
            cache.del(okeys);
        } catch (Exception e) {
            broken = true;
            throw new CacheException(e);
        } finally {
            RedisCacheProvider.returnResource(cache, broken);
        }
    }

 但是关键是这个方法里面又去获得了一个新的Redis对象。

public EhCache buildCache(String name, boolean autoCreate, CacheExpiredListener listener) throws CacheException {
     EhCache ehcache = _CacheManager.get(name);
     if(ehcache == null && autoCreate){
         try {
             synchronized(_CacheManager){
                 ehcache = _CacheManager.get(name);
                 if(ehcache == null){
                     net.sf.ehcache.Cache cache = manager.getCache(name);
                     if (cache == null) {
                         log.warn("Could not find configuration [" + name + "]; using defaults.");
                         manager.addCache(name);
                         cache = manager.getCache(name);
                         log.debug("started EHCache region: " + name);                
                     }
                     ehcache = new EhCache(cache, listener);
                     _CacheManager.put(name, ehcache);
                 }
             }
         }
         catch (net.sf.ehcache.CacheException e) {
             throw new CacheException(e);
         }
     }
     return ehcache;
 }

 这个方法写得实在是醉了,呵呵,太难看了。
这里关键在于:如果autoCreate是个false,你永远拿到的是null。那么问题来了,如果autoCreate只能是true,这个参数还有意义么?

再一个问题,如果返回一个null,让使用的同学们如何用?写成下面这个样子么??

if(xxx!=null){

doSomeThing....

}

忽然在net.oschina.j2cache中又发现一个类CacheTester.java

 

总结一下:


J2Cache比我想像中要小许多,简单易用,当然再注重一下细节就更好了。

 

附:Tiny成员会出现请客的情况:

 

System.out.print用在不应该出现的地方
不适当的使用main方法。
方法函数行数太长
圈复杂度太大--超过10
异常处理处理不好:应该有没有,不应该有有了,抓到异常没有说明也没有任何处理
造成Maven循环依赖了
已经测试完成的代码,出现导致整个系统崩溃的问题了
提交了编译通不过的代码到配置库的
提交了不应该提交的内容到配置库的
已修正Issue但是不在git上关闭的。
Sonar规则检查通过率85%以下的
悠然判定认为需要请客的

 

欢迎登录关注:http://bbs.tinygroup.org,本例涉及的代码和框架资料,将会在论坛分享。技术交流群:228977971,让我们一起动手,了解框架的奥秘!

J2Cache是OSChina目前正在使用的两级缓存框架(要求至少 Java 8)。第一级缓存使用内存(同时支持 Ehcache 2.x、Ehcache 3.x 和 Caffeine),第二级缓存使用 Redis(推荐)/Memcached。由于大量的缓存读取会导致L2的网络成为整个系统的瓶颈,因此L1的目标是降低对L2的读取次数。该缓存框架主要用于集群环境中。单机也可使用,用于避免应用重启导致的缓存冷启动后对后端业务的冲击。 数据读取: 读取顺序 -> L1 -> L2 -> DB 数据更新 1、从数据库中读取最新数据,依次更新L1 -> L2 ,发送广播清除某个缓存信息 2、接收到广播(手工清除缓存 & 一级缓存自动失效),从L1中清除指定的缓存信息 J2Cache配置: 配置文件位于core/resources目录下,包含三个文件: j2cache.properties J2Cache核心配置文件,可配置两级的缓存,Redis服务器、连接池以及缓存广播的方式 caffeine.properties如果一级缓存选用Caffeine ,那么该文件用来配置缓存信息 ehcache.xml Ehcache的配置文件,配置说明请参考Ehcache文档 ehcache3.xml Ehcache3的配置文件,配置说明请参考Ehcache文档 network.xml JGroups网络配置,如果使用JGroups组播的话需要这个文件,一般无需修改 实际使用过程需要将所需的配置文件复制到应用类路径中,如WEB-INF/classes目录。 J2Cache运行时所需jar包请查看core/pom.xml 测试方法: 1、安装Redis 2git clone https://gitee.com/ld/J2Cache 3、修改core/resource/j2cache.properties配置使用已安装的Redis服务器 4、在命令行中执行mvn package -DskipTests=true进行项目编译 5、打开多个命令行窗口,同时运行runtest.sh 6、在 > 提示符后输入help查看命令,并进行测试
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值