辛德蕾拉|面试官:Redis缓存了解吗?面对这11道题是否有很多问号?( 四 )


但是问题是 , 定期删除可能会导致很多过期 key 到了时间并没有被删除掉 , 那咋整呢?所以就是惰性删除了 。 这就是说 , 在你获取某个 key 的时候 , redis 会检查一下, 这个 key 如果设置了过期时间那么是否过期了?如果过期了此时就会删除 , 不会给你返回任何东西 。
获取 key 的时候 , 如果此时 key 已经过期 , 就删除 , 不会返回任何东西 。
答案是:走内存淘汰机制 。
内存淘汰机制
redis 内存淘汰机制有以下几个:

  • noeviction: 当内存不足以容纳新写入数据时 , 新写入操作会报错 , 这个一般没人用吧 , 实在是太恶心了 。
  • allkeys-lru:当内存不足以容纳新写入数据时 , 在键空间中 , 移除最近最少使用的 key(这个是最常用的) 。
  • allkeys-random:当内存不足以容纳新写入数据时 , 在键空间中 , 随机移除某个 key , 这个一般没人用吧 , 为啥要随机 , 肯定是把最近最少使用的 key 给干掉啊 。
  • volatile-lru:当内存不足以容纳新写入数据时 , 在设置了过期时间的键空间中 , 移除最近最少使用的 key(这个一般不太合适) 。
  • volatile-random:当内存不足以容纳新写入数据时 , 在设置了过期时间的键空间中 , 随机移除某个 key 。
  • volatile-ttl:当内存不足以容纳新写入数据时 , 在设置了过期时间的键空间中 , 有更早过期时间的 key 优先移除 。
手写一个 LRU 算法
你可以现场手写最原始的 LRU 算法 , 那个代码量太大了 , 似乎不太现实 。
不求自己纯手工从底层开始打造出自己的 LRU , 但是起码要知道如何利用已有的 JDK 数据结构实现一个Java 版的 LRU 。
class LRUCache extends LinkedHashMap {private final int CACHE_SIZE;/*** 传递进来最多能缓存多少数据 ** @param cacheSize 缓存大小 */public LRUCache(int cacheSize) {// true 表示让 linkedHashMap 按照访问顺序来进行排序 , 最近访问的放在头部 , 最老访问的 放在尾部 。super((int) Math.ceil(cacheSize / 0.75) + 1, 0.75f, true);CACHE_SIZE = cacheSize;}@Overrideprotected Boolean removeEldestEntry(Map.Entry eldest) {// 当 map 中的数据量大于指定的缓存个数的时候 , 就自动删除最老的数据 。return size() > CACHE_SIZE;}}5、如何保证 redis 的高并发和高可用?redis 的主从复制原理能介绍一下么?redis 的哨兵原理能介绍一下么?面试官心理分析其实问这个问题 , 主要是考考你 , redis 单机能承载多高并发?如果单机扛不住如何扩容扛更多的并发?redis 会不会挂?既然 redis 会挂那怎么保证 redis 是高可用的?
其实针对的都是项目中你肯定要考虑的一些问题 , 如果你没考虑过 , 那确实你对生产系统中的问题思考太少 。
面试题剖析如果你用 redis 缓存技术的话 , 肯定要考虑如何用 redis 来加多台机器 , 保证 redis 是高并发的 , 还有就是如何让 redis 保证自己不是挂掉以后就直接死掉了 , 即 redis 高可用 。
由于此节内容较多 , 因此 , 会分为两个小节进行讲解 。- redis 主从架构 - redis 基于哨兵实现高可用redis 实现高并发主要依靠主从架构 , 一主多从 , 一般来说 , 很多项目其实就足够了 , 单主用来写入数据 , 单机几万 QPS , 多从用来查询数据 , 多个从实例可以提供每秒 10w 的 QPS 。
如果想要在实现高并发的同时 , 容纳大量的数据 , 那么就需要 redis 集群 , 使用 redis 集群之后 , 可以提供每秒几十万的读写并发 。
redis 高可用 , 如果是做主从架构部署 , 那么加上哨兵就可以了 , 就可以实现 , 任何一个实例宕机 , 可以进行主备切换 。
6、redis 的持久化有哪几种方式?不同的持久化机制都有什么 优缺点?持久化机制具体底层是如何实现的?面试官心理分析redis 如果仅仅只是将数据缓存在内存里面 , 如果 redis 宕机了再重启 , 内存里的数据就全部都弄丢了啊 。


推荐阅读