Redis 三连问:为什么要用 Redis?为什么是单线程的?缓存雪崩?

  • 面试题 1:为什么要用 Redis ?业务在哪块儿用到的?

  • 追问 1:Redis 里有哪些数据类型?

  • 追问 2:Redis 与 Memcached 有哪些区别?

  • 追问 3:那 Redis 怎样防止异常数据不丢失的?如何持久化?

  • 面试题 2:Redis 为啥是单线程的?

  • 追问 1:单线程只使用了单核 CPU,太浪费,有什么办法发挥多核 CPU 的性能嘛?

  • 面试题 3:聊一下对缓存穿透、缓存击穿、缓存雪崩的理解吧?

  • 追问 1:那你说一下针对缓存击穿的解决方法?

面试题 1:为什么要用 Redis ?业务在哪块儿用到的?

正经回答:

Redis 是眼下最为人熟知的缓解高并发、提升高可用能力的手段之一,在提升服务器性能方面效果显著。

这里不得不提到高并发场景,我们知道,并发场景下核心点在数据库,引入缓存(以及引入任何负载均衡、集群等策略)的目的都是在减轻数据库压力,让更多原本打到 DB 上的请求,在中间被拦截处理掉。就像你请个假屁大点儿事还要大老板签字一样?

深入追问:

追问 1:Redis 里有哪些数据类型?

丰富的数据类型,Redis 有 8 种数据类型,当然常用的主要是 String、Hash、List、Set、 SortSet 这 5 种类型,他们都是基于键值的方式组织数据。每一种数据类型提供了非常丰富的操作命令,可以满足绝大部分需求,如果有特殊需求还能自己通过 lua 脚本自己创建新的命令(具备原子性);

  • memcached 所有的值均是简单的字符串,redis 作为其替代者,支持更为丰富的数据类型

  • redis 的速度比 memcached 快很多

  • redis 可以持久化数据到磁盘,这个很关键,宕机断电不再是硬伤。

追问 3:那 Redis 怎样防止异常数据不丢失的?如何持久化?

RDB 持久化 (快照)

  • 将某个时间点的所有数据生成快照,存放到硬盘上。当数据量很大时,会很慢。

  • 可以将快照复制到其它服务器从而创建具有相同数据的服务器副本。

  • 如果系统发生故障,将会丢失最后一次创建快照之后的数据。

AOF 持久化(即时更新)

  • 将写命令添加到 AOF 文件(Append Only File)的末尾。

  • 使用 AOF 持久化需要设置同步选项,从而确保写命令同步到磁盘文件上的时机。这是因为对文件进行写入并不会马上将内容同步到磁盘上,而是先存储到缓冲区,然后由操作系统决定什么时候同步到磁盘。

有以下同步选项(同步频率): always 每个写命令都同步;everysec 每秒同步一次;no 让操作系统来决定何时同步。everysec 选项比较合适,可以保证系统崩溃时只会丢失一秒左右的数据,并且 Redis 每秒执行一次同步对服务器性能几乎没有任何影响

面试题 2:Redis 为啥是单线程的?

Redis is single threaded. How can I exploit multiple CPU / cores?It’s not very frequent that CPU becomes your bottleneck with Redis, as usually Redis is either memory or network bound. For instance, using pipelining Redis running on an average Linux system can deliver even 1 million requests per second, so if your application mainly uses O(N) or O(log(N)) commands, it is hardly going to use too much CPU.However, to maximize CPU usage you can start multiple instances of Redis in the same box and treat them as different servers. At some point a single box may not be enough anyway, so if you want to use multiple CPUs you can start thinking of some way to shard earlier.You can find more information about using multiple Redis instances in the Partitioning page.However with Redis 4.0 we started to make Redis more threaded. For now this is limited to deleting objects in the background, and to blocking commands implemented via Redis modules. For future releases, the plan is to make Redis more and more threaded.

正经回答:

上面是 Redis 官网给的解释(官方文档链接),翻译后简单说,因为 Redis 的瓶颈不是 CPU 的运行速度,而往往是网络带宽和机器的内存大小。再说了,单线程切换开销小,容易实现。既然单线程容易实现,而且 CPU 不会成为瓶颈,那就顺理成章地采用单线程的方案,当然了,也是为了避免多线程存在的很多坑。对了,一个节点是一个单线程。

深入追问:

追问 1:单线程只使用了单核 CPU,太浪费,有什么办法发挥多核 CPU 的性能嘛?

我们可以通过在单机开多个 Redis 实例,我们一直在强调的单线程,只是在处理我们的网络请求的时候只有一个线程来处理。实际上,一个正式的 Redis Server 运行的时候肯定是不止一个线程的,都是集群形式,多少多少个节点,所以实际环境中大家不用担心这种问题。

面试题 3:聊一下对缓存穿透、缓存击穿、缓存雪崩的理解吧

正经回答:

  • 缓存穿透:指缓存和数据库中都没有的数据,导致所有的请求都打到数据库上,然后数据库还查不到(如 null),造成数据库短时间线程数被打满而导致其他服务阻塞,最终导致线上服务不可用,这种情况一般来自黑客同学。

  • 缓存击穿:指缓存中没有但数据库中有的数据(一般是热点数据缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去查,引起数据库压力瞬间增大,线上系统卡住。

  • 缓存雪崩:指缓存同一时间大面积的失效,缓存击穿升级版。

深入追问:

追问 1:那你说一下针对缓存击穿的解决方法?

根据实际业务情况,在 Redis 中维护一个热点数据表,批量设为永不过期(如 top1000),并定时更新 top1000 数据。加互斥锁(mutex key)互斥锁缓存击穿后,多个线程会同时去查询数据库的这条数据,那么我们可以在第一个查询数据的请求上使用一个互斥锁来锁住它。其他的线程走到这一步拿不到锁就等着,等第一个线程查询到了数据,然后做缓存。后面的线程进来发现已经有缓存了,就直接走缓存。

static Lock reenLock = new ReentrantLock();
    public List<String> getData04() throws InterruptedException {
        List<String> result = new ArrayList<String>();
        // 从缓存读取数据
        result = getDataFromCache();
        if (result.isEmpty()) {
            if (reenLock.tryLock()) {
                try {
                    System.out.println("拿到锁了,从DB获取数据库后写入缓存");
                    // 从数据库查询数据
                    result = getDataFromDB();
                    // 将查询到的数据写入缓存
                    setDataToCache(result);
                } finally {
                    reenLock.unlock();// 释放锁
                }


            } else {
                result = getDataFromCache();// 先查一下缓存
                if (result.isEmpty()) {
                    System.out.println("我没拿到锁,缓存也没数据,先小憩一下");
                    Thread.sleep(100);// 小憩一会儿
                    return getData04();// 重试
                }
            }
        }
        return result;
    }

小结

今天我们复习了面试中常考的 Redis 三个问题,你做到心中有数了么?对了,如果你的朋友也在准备面试,请将这个系列扔给他,如果他认真对待,肯定会感谢你的!!

本文文字及图片出自 InfoQ

本文文字及图片出自

余下全文(1/3)
分享这篇文章:

请关注我们:

共有 8 条讨论

  1. admin  这篇文章, 并对这篇文章的反应是'+(41554*40455)+'
  2. admin  这篇文章
  3. admin  这篇文章
  4. admin  这篇文章
  5. admin  这篇文章
  6. admin  这篇文章
  7. admin  这篇文章
  8. admin  这篇文章

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注