缓存的设计 缓存的例子

如何设计一个本地缓存?需要考虑哪些方面?

缓存的应用很多,比如操作系统中的页面置换,计算机网络中的网站缓存,DNS缓存,数据库中的缓存 

更多场景设计题参看:

场景设计题 汇总 (一)_trigger333的博客-CSDN博客

目录

缓存需要考虑的点

1.数据结构

2.对象上限

3.清除策略

4.过期时间

5.线程安全

6.简明的接口

7.是否持久化

8.阻塞机制

具体例子

面试官:给我实现一下带有过期时间的LRU(java版)

Redis中的缓存策略

操作系统中的页面置换

DNS的缓存,浏览器页面的缓存,内容分发网络CDN也是缓存。


面试官:设计一个本地缓存,需要考虑那些点?_胡庚申的博客-CSDN博客

缓存需要考虑的点

考虑点主要在数据用何种方式存储,能存储多少数据,多余的数据如何处理等几个点,

1.数据结构

首要考虑的就是数据该如何存储,用什么数据结构存储,最简单的就直接用Map来存储数据;或者复杂的如redis一样提供了多种数据类型哈希,列表,集合,有序集合等,底层使用了双端链表,压缩列表,集合,跳跃表等数据结构;

2.对象上限

因为是本地缓存,内存有上限,所以一般都会指定缓存对象的数量比如1024,当达到某个上限后需要有某种策略去删除多余的数据;

3.清除策略

上面说到当达到对象上限之后需要有清除策略,常见的比如有LRU(最近最少使用)、FIFO(先进先出)、LFU(最近最不常用)、SOFT(软引用)、WEAK(弱引用)等策略;

4.过期时间

除了使用清除策略,一般本地缓存也会有一个过期时间设置,比如redis可以给每个key设置一个过期时间,这样当达到过期时间之后直接删除,采用清除策略+过期时间双重保证;

5.线程安全

像redis是直接使用单线程处理,所以就不存在线程安全问题;而我们现在提供的本地缓存往往是可以多个线程同时访问的,所以线程安全是不容忽视的问题;并且线程安全问题是不应该抛给使用者去保证;

6.简明的接口

提供一个傻瓜式的对外接口是很有必要的,对使用者来说使用此缓存不是一种负担而是一种享受;提供常用的get,put,remove,clear,getSize方法即可;

7.是否持久化

这个其实不是必须的,是否需要将缓存数据持久化看需求;本地缓存如ehcache是支持持久化的,而guava是没有持久化功能的;分布式缓存如redis是有持久化功能的,memcached是没有持久化功能的;

8.阻塞机制

在看Mybatis源码的时候,二级缓存提供了一个blocking标识,表示当在缓存中找不到元素时,它设置对缓存键的锁定;这样其他线程将等待此元素被填充,而不是命中数据库;其实我们使用缓存的目的就是因为被缓存的数据生成比较费时,比如调用对外的接口,查询数据库,计算量很大的结果等等;这时候如果多个线程同时调用get方法获取的结果都为null,每个线程都去执行一遍费时的计算,其实也是对资源的浪费;最好的办法是只有一个线程去执行,其他线程等待,计算一次就够了;但是此功能基本上都交给使用者来处理,很少有本地缓存有这种功能;

具体例子

面试官:给我实现一下带有过期时间的LRU(java版)

在Node中加入过期时间属性,表示该缓存key在 time时间过期。

在添加缓存时,也把缓存加入到一个小根堆中,堆顶表示过期时间最近的缓存。

再起一个线程,while true循环判断 堆顶缓存是否已经过期,如果过期就删除,没有过期就继续判断。

Redis中的缓存策略

Redis 提供 8 种数据淘汰策略
两种LRU 不同是删除数据的集合不同 第一种是已设置过期时间的数据集
第二种是当前的键空间,包含所有的键。


两种LFU的区别和LRU一样。
1. volatile-lru ( least recently used ) :从已设置过期时间的数据集( server.db[i].expires )
中挑选最近最少使⽤的数据淘汰
2. volatile-ttl :从已设置过期时间的数据集( server.db[i].expires )中挑选将要过期的数据淘汰
3. volatile-random :从已设置过期时间的数据集( server.db[i].expires )中任意选择数据淘汰
4. allkeys-lru(least recently used):当内存不⾜以容纳新写⼊数据时,在键空间中,移除
最近最少使⽤的 key(这个是最常⽤的)
5. allkeys-random :从数据集( server.db[i].dict )中任意选择数据淘汰
6. no-eviction :禁⽌驱逐数据,也就是说当内存不⾜以容纳新写⼊数据时,新写⼊操作会报
错。
7. volatile-lfu ( least frequently used ) :从已设置过期时间的数据集 (server.db[i].expires) 中
挑选最不经常使⽤的数据淘汰
8. allkeys-lfu ( least frequently used ) :当内存不⾜以容纳新写⼊数据时,在键空间中,移
除最不经常使⽤的 key
 

操作系统中的页面置换

最优置换算法

先进先出算法

LRU算法

DNS的缓存,浏览器页面的缓存,内容分发网络CDN也是缓存。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

trigger333

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值