FreyjaJdbcTemplate特性二:cache
在使用hibernate开发过程中,让我一直感到奇怪的是为什么缓存是如此的让人不顺心。对于update操作频繁的项目更是噩梦。这和我对缓存的理解有很大的出入。
我的想法有2点:
1、数据库是大海,缓存是池塘。如果我抓了4条鱼到池塘里面去,为什么我一直要做这么一件事情:把鱼抓到池塘里面过一段时间又放回大海,过一段时间又抓到池塘里面去。这样真傻。还有一个诡异的问题,鱼被抓到池塘里面了,大海里面的鱼是哪来的?
2、如果我要抓所有的鲶鱼,难道我只去池塘抓?如果我怎么才能知道池塘的鱼是不是就是所有的鲶鱼了,这个时候必须去大海里面再捞一捞。必须去大海里面一次又一次的捞?要池塘又是干嘛的?
freyja的做法:
1、在freyja里面鱼只有一条,要么在池塘要么在海里面。freyja用hashMap来管理缓存(ehcache)
2、get方式获取到的都是优先缓存内的值,取不到才会去发送sql并且放入cache中。
find()方法会发送sql去查找id,然后遍历缓存,如果缓存中存在者返回缓存中的值,否则取数据库中的。
executeUpdate()方法会直接update数据库,并且会select id 找出涉及到的表的id然后用el工具更新缓存中的值。来维护缓存。
将要实现的cache能力:
3、第一次发送sql会查询出一个记录集,第二次发送sql着直接取缓存中的内容。难点是,如果其中一条记录的条件变化,如何完成这个处理?我的想法是一条记录保存所有缓存他得key,一旦update操作则让其缓存失效(这个是简单做法,复杂做法是根据条件再次判断是否让缓存失效。)
4、(这是我最喜欢的一个功能)no update。
这个功能的特点就是在update(user)的时候不会去发送sql update数据库。也就是第一点所说的,鱼在池塘就不去理会大海。这个功能的思路大概有了,正在施工中。但是工作量很大,而且效率怎么样不得而之。总之,这是自寻死路。
对于现在的freyja来说不支持分布式,也许以后会去考虑,一旦支持了分布式那么我的第一个理念就有出入了。
其实还有最大的一个问题:事务
http://freyja.iteye.com/blog/1178182
事务的特性就是为了让一个人不要在看书的时候听音乐。因为同时做2件事的时候容易出问题。事务还是很有存在的必要的,但是freyja的结构让事务失去了作用。只有一个对象的freyja可以在事物里面的数据被事物外的数据修改。
freyja对事物的处理是,在get()实体的时候根据事物的id为key把结果集放入一个map作为副本,在出错的时候”回滚“,事物结束的时候remove key。这部分还在完善中。
在简单的测试中,hibernate一级缓存情况下的select update 操作freyja和hibernate效率相当。(因为freyja本身就是一个大的一级缓存)。但是到了重要的二级缓存里面hibernate和freyja没有可比性了。
如这么一个测试:@Test
public void testFind() { long l1 = System.currentTimeMillis(); for (int i = 0; i < 2000; i++) { userService.testFind(); } long l2 = System.currentTimeMillis(); System.out.println("freyja find() 5000个对象耗时:" + (l2 - l1) / 1000); } public void testFind() { for (int i = 0; i < 10; i++) { List<User> list = baseDAO.find(User.class, "level < ?", i); } }
模拟二级缓存环境,数据源用的是同一个,hibernate的二级缓存开启查询缓存关闭(难道开启会好点?)
hibernate find() 5000个对象耗时:11 (500*10)
hibernate find() 5000个对象耗时:20 (1000*10)
hibernate find() 5000个对象耗时:40 (2000*10)
freyja find() 5000个对象耗时:7 (500*10)
freyja find() 5000个对象耗时:13 (1000*10)
freyja find() 5000个对象耗时:25 (2000*10)
分别是2000调用、1000次调用和500次调用。User表里面有5000条记录,level为1-5000;
这个差距大概体现在hibernate每次从缓存中提取结果需要序列化的原因。
还是等完全施工完毕再全面的系统测试一次比较好。
那个时候hibernate有它的一套完备的体系,freyja则有自己的原生sql+cache支持。
FreyjaJdbcTemplate特性一:HQL
FreyjaJdbcTemplate特性二:cache
FreyjaJdbcTemplate特性三:JdbcTemplate