Java缓存技术怎么使用
发布时间:2023-04-22 13:45:58 所属栏目:教程 来源:
导读:为什么我们需要缓存?
很久很久以前,在还没有缓存的时候……用户经常是去请求一个对象,而这个对象是从数据库去取,然后,这个对象变得越来越大,这个用户每次的请求时间也越来越长了,这也把数据库
很久很久以前,在还没有缓存的时候……用户经常是去请求一个对象,而这个对象是从数据库去取,然后,这个对象变得越来越大,这个用户每次的请求时间也越来越长了,这也把数据库
|
为什么我们需要缓存? 很久很久以前,在还没有缓存的时候……用户经常是去请求一个对象,而这个对象是从数据库去取,然后,这个对象变得越来越大,这个用户每次的请求时间也越来越长了,这也把数据库弄得很痛苦,他无时不刻不在工作。所以,这个事情就把用户和数据库弄得很生气,接着就有可能发生下面两件事情: 1.用户很烦,在抱怨,甚至不去用这个应用了(这是大多数情况下都会发生的) 2.数据库为打包回家,离开这个应用,然后,就出现了麻烦(没地方去存储数据了)(发生在极少数情况下) 什么是缓存? 正如开篇所讲,缓存是“存贮数据(使用频繁的数据)的临时地方,因为取原始数据的代价太大了,所以我可以取得快一些。” 缓存可以认为是数据的池,这些数据是从数据库里的真实数据复制出来的,并且为了能正确取回,被标上了标签(键 ID)。太棒了 programmer one 已经知道这点了,但是他还不知道下面的缓存术语。 命中: 当客户发起一个请求(我们说他想要查看一个产品信息),我们的应用接受这个请求,并且如果是在第一次检查缓存的时候,需要去数据库读取产品信息。 如果在缓存中,一个条目通过一个标记被找到了,这个条目就会被使用、我们就叫它缓存命中。所以,命中率也就不难理解了。 Cache Miss: 但是这里需要注意两点: 1. 如果还有缓存的空间,那么,没有命中的对象会被存储到缓存中来。 2. 如果缓存满了,而又没有命中缓存,那么就会按照某一种策略,把缓存中的旧对象踢出,而把新的对象加入缓存池。而这些策略统称为替代策略(缓存算法),这些策略会决定到底应该提出哪些对象。 没有人能说清哪种缓存算法优于其他的缓存算法 Least Frequently Used(LFU): 大家好,我是 LFU,我会计算为每个缓存对象计算他们被使用的频率。我会把最不常用的缓存对象踢走。 Least Recently User(LRU): 我是 LRU 缓存算法,我把最近最少使用的缓存对象给踢走。 我总是需要去了解在什么时候,用了哪个缓存对象。如果有人想要了解我为什么总能把最近最少使用的对象踢掉,是非常困难的。 浏览器就是使用了我(LRU)作为缓存算法。新的对象会被放在缓存的顶部,当缓存达到了容量极限,我会把底部的对象踢走,而技巧就是:我会把最新被访问的缓存对象,放到缓存池的顶部。 所以,经常被读取的缓存对象就会一直呆在缓存池中。有两种方法可以实现我,array 或者是 linked list。 我的速度很快,我也可以被数据访问模式适配。我有一个大家庭,他们都可以完善我,甚至做的比我更好(我确实有时会嫉妒,但是没关系)。我家庭的一些成员包括 LRU2 和 2Q,他们就是为了完善 LRU 而存在的。 First in First out(FIFO): 我是先进先出,我是一个低负载的算法,并且对缓存对象的管理要求不高。我通过一个队列去跟踪所有的缓存对象,最近最常用的缓存对象放在后面,而更早的缓存对象放在前面,当缓存容量满时,排在前面的缓存对象会被踢走,然后把新的缓存对象加进去。我很快,但是我并不适用。 Second Chance: 大家好,我是 second chance,我是通过 FIFO 修改而来的,被大家叫做 second chance 缓存算法,我比 FIFO 好的地方是我改善了 FIFO 的成本。我是 FIFO 一样也是在观察队列的前端,但是很FIFO的立刻踢出不同,我会检查即将要被踢出的对象有没有之前被使用过的标志(1一个 bit 表示),没有被使用过,我就把他踢出;否则,我会把这个标志位清除,然后把这个缓存对象当做新增缓存对象加入队列。你可以想象就这就像一个环队列。当我再一次在队头碰到这个对象时,由于他已经没有这个标志位了,所以我立刻就把他踢开了。我在速度上比 FIFO 快。 其他的缓存算法还考虑到了下面几点: 成本:如果缓存对象有不同的成本,应该把那些难以获得的对象保存下来。 容量:如果缓存对象有不同的大小,应该把那些大的缓存对象清除,这样就可以让更多的小缓存对象进来了。 时间:一些缓存还保存着缓存的过期时间。电脑会失效他们,因为他们已经过期了。 根据缓存对象的大小而不管其他的缓存算法可能是有必要的。 看看缓存元素(缓存实体) public class CacheElement { private Object objectValue; private Object objectKey; private int index; private int hitCount; // getters and setters } 这个缓存实体拥有缓存的key和value,这个实体的数据结构会被以下所有缓存算法用到。 缓存算法的公用代码 public final synchronized void addElement(Object key, Object value) { int index; Object obj; // get the entry from the table obj = table.get(key); // If we have the entry already in our table // then get it and replace only its value. obj = table.get(key); if (obj != null) { CacheElement element; element = (CacheElement) obj; element.setobjectValue(value); element.setobjectKey(key); return; } } (编辑:汽车网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
推荐文章
站长推荐
