Java面试题冲刺第二天--Redis篇

目录
  • 面试题1:为什么要用 Redis ?业务在哪块儿用到的?
    • 正经回答:
      • 深入追问: 追问1:Redis里有哪些数据类型?
      • 追问2:Redis与Memcached有哪些区别?
      • 追问3:那Redis怎样防止异常数据不丢失的?如何持久化?
  • 面试题2:Redis为啥是单线程的?
    • 正经回答:
    • 深入追问:
      • 追问1:单线程只使用了单核CPU,太浪费,有什么办法发挥多核CPU的性能嘛?
  • 面试题3:聊一下对缓存穿透、缓存击穿、缓存雪崩的理解吧
    • 正经回答:
    • 深入追问:
      • 追问1:那你说一下针对缓存击穿的解决方法
  • 总结

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

正经回答:

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

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

通俗易懂点儿说,高并发对服务器来说,就好比你被人锤一拳,这拳头可是硬的很,光着膀子的话一拳就给我干吐血。。那么我为了承受住这一拳?穿棉袄、穿护垫、穿…是吧,只要够厚,我都以为你在给我挠痒痒~同理,Redis就是一件又厚又弹的棉袄。

话说回来,它有多厚多弹呢?操作缓存就是直接操作内存,速度相当快,直接操作缓存能够承受的请求数是远远大于直接访问数据库的。

Redis优势:

  • 读写性能优异, Redis能读的速度是110000次/s,写的速度是81000次/s。
  • 支持数据持久化,支持AOF和RDB两种持久化方式。
  • 支持事务,Redis的所有操作都是原子性的,同时Redis还支持对几个操作合并后的原子性执行。
  • 数据结构丰富,除了支持string类型的value外还支持hash、set、zset、list等数据结构。
  • 支持主从复制,主机会自动将数据同步到从机,可以进行读写分离。
  • 支持大量集群节点。

假如用户第一次访问数据库中的某些数据。这个过程会比较慢,因为是从硬盘上读取的。将该用户访问的数据存在数Redis中,这样下一次再访问这些数据的时候就可以直接从缓存中获取了。同样,我们可以把数据库中的部分数据转移到缓存中去,这样用户的一部分请求会直接打到缓存而不是数据库(即半路拦截掉了)。如果数据库中的对应数据改变的之后,同步改变缓存中相应的数据即可!

在我们业务中,包括热点词查询、一些实时排行榜数据、访问量点赞量统计、Session共享等等都可以引入Redis来处理。

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

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

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

两者都是非关系型内存键值数据库,现在公司一般都是用 Redis 来实现缓存,为什么不用Memcached呢?

参数 Redis Memcached
类型 1. 支持内存 2. 非关系型数据库 1. 支持内存 2. 键值对形式 3. 缓存形式
数据存储类型 1. String 2. List 3. Set 4. Hash 5. Sort Set 1. 文本型 2. 二进制类型
附加功能 1. 发布/订阅模式 2. 主从分区 3. 序列化支持 4. 脚本支持【Lua脚本】 多线程服务支持
网络IO模型 单线程的多路 IO 复用模型 多线程,非阻塞IO模式
持久化支持 1. RDB 2. AOF 不支持
集群模式 原生支持 cluster 模式,可以实现主从复制,读写分离 没有原生的集群模式,需要依靠客户端来实现往集群中分片写入数据
内存管理机制 在 Redis 中,并不是所有数据都一直存储在内存中,可以将一些很久没用的 value 交换到磁盘 Memcached 的数据则会一直在内存中,Memcached 将内存分割成特定长度的块来存储数据,以完全解决内存碎片的问题。
适用场景 复杂数据结构,有持久化,高可用需求,value存储内容较大,最大512M 纯key-value,数据量非常大,并发量非常大的业务
  • 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:那你说一下针对缓存击穿的解决方法

  1. 根据实际业务情况,在Redis中维护一个热点数据表,批量设为永不过期(如top1000),并定时更新top1000数据。
  2. 加互斥锁(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;
    }

总结

本篇文章就到这里了,希望能给你带来帮助,也希望您能够多多关注我们的更多内容!

(0)

相关推荐

  • Java 面试题基础知识集锦

    经典的Java基础面试题集锦,欢迎收藏和分享. 问题:如果main方法被声明为private会怎样? 答案:能正常编译,但运行的时候会提示"main方法不是public的". 问题:Java里的传引用和传值的区别是什么? 答案:传引用是指传递的是地址而不是值本身,传值则是传递值的一份拷贝. 问题:如果要重写一个对象的equals方法,还要考虑什么? 答案:hashCode. 问题:Java的"一次编写,处处运行"是如何实现的? 答案:Java程序会被编译成字节码组成

  • Java基础之Integer使用的注意事项及面试题

    JAVA中Integer对象的引用 JAVA中没有指针一说,但也有引用的概念.这里要说的主要是Integer是不是同一个对象. 1.先看一段代码: public static void main(String[] args){ Integer a1 = 100; Integer b1 = a1;//另一种也可以b1=100 Field field = null; try { field = a1.getClass().getDeclaredField("value"); } catch

  • JAVA基础面试题整理

    1.Java中final.finally.finalize的区别 简单区别: final用于声明属性,方法和类,分别表示属性不可交变,方法不可覆盖,类不可继承. finally是异常处理语句结构的一部分,表示总是执行. finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,供垃圾收集时的其他资源回收,例如关闭文件等. 2.error和exception有什么区别? Error(错误)表示系统级的错误和程序不必处理的异常,是java运行环境中的内部错误或者硬件

  • Java面试题及答案集锦(基础题122道,代码题19道)

    Java基础面试题及答案集锦(基础题122道,代码题19道),具体详情如下所示: 1.面向对象的特征有哪些方面 1.抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面.抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节.抽象包括两个方面,一是过程抽象,二是数据抽象. 2.继承: 继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法.对象的一个新类可以从现有的类中派生,这个过程称为类继承.新类继承了原始类的特性

  • 经典的Java面试题及回答集锦(基础篇)

    1.问题:如果A和B对象循环引用,是否可以被GC? 回答:可以,现在的虚拟机基本都是通过可达性分析算法来判断对象是否存活的,而不是通过简单的引用计数法来判断对象是否存活.可达性分析算法使用一系列的"GC Roots"对象(虚拟机栈中引用的对象.静态属性引用对象)作为起始点,这些节点向下搜索的路径称为引用链,当一个对象到GC Roots没有任何引用链连接,则证明对象是不可用的. 2.Java中的内存溢出是如何造成的? OutOfMemoryError: (1)PerGern Space

  • Java面试题冲刺第二天--Redis篇

    目录 面试题1:为什么要用 Redis ?业务在哪块儿用到的? 正经回答: 深入追问: 追问1:Redis里有哪些数据类型? 追问2:Redis与Memcached有哪些区别? 追问3:那Redis怎样防止异常数据不丢失的?如何持久化? 面试题2:Redis为啥是单线程的? 正经回答: 深入追问: 追问1:单线程只使用了单核CPU,太浪费,有什么办法发挥多核CPU的性能嘛? 面试题3:聊一下对缓存穿透.缓存击穿.缓存雪崩的理解吧 正经回答: 深入追问: 追问1:那你说一下针对缓存击穿的解决方法

  • Java面试题冲刺第二十六天--实战编程

    目录 面试题1:你们是怎样保存用户密码等敏感数据的? 面试题2:怎么控制用户请求的幂等性的? 1.设置唯一索引:防止新增脏数据 2.token机制:防止页面重复提交 3.悲观锁 4.乐观锁 5.分布式锁 面试题3:你们是如何预防SQL注入问题的? 预防方式: 1.PreparedStatement(简单有效) 2.使用正则表达式过滤传入的参数 3.使用正则表达式过滤传入的URL 总结 面试题1:你们是怎样保存用户密码等敏感数据的? 本题回答参考朱晔的<Java业务开发常见错误100例> 我们知

  • Java面试题冲刺第二十三天--算法(2)

    目录 面试题1:你说一下常用的排序算法都有哪些? 追问1:谈一谈你对快排的理解吧 追问2:说一下快排的算法原理 追问3:来吧!给我手敲一个快排 面试题2:来!再给我手撸一个Spring 追问1:哦,咳咳-说一下构成递归的前提条件有啥? 追问2:递归都有哪些优缺点? 追问3:给我手写一个简单的递归算法的实现吧 面试题3: 10亿个数中找出最大的100000个数(top K问题) 总结 面试题1:你说一下常用的排序算法都有哪些? 追问1:谈一谈你对快排的理解吧 快速排序,顾名思义就是一种以效率快为特

  • Java面试题冲刺第二十五天--实战编程2

    目录 面试题2:怎么理解负载均衡的?你处理负载均衡都有哪些途径? 1.[协议层]http重定向 2.[协议层]DNS轮询 3.[协议层]CDN 4.[协议层]反向代理负载均衡 5.[网络层]IP负载均衡 面试题3:你平时是怎样定位线上问题的? 总结 面试题1:当你发现一条SQL很慢,你的处理思路是什么? 发现Bug 确定Bug不是自己造成的,如果无法确定,不要理会步骤1 向组内宣传"程序里有一个未知Bug,错不在我" 谁响应,谁对Bug负责 没人响应,就要求特定人员配合调试 如果不配合

  • Java面试题冲刺第二十六天--实战编程2

    目录 面试题2:怎么理解负载均衡的?你处理负载均衡都有哪些途径? 1.[协议层]http重定向 2.[协议层]DNS轮询 3.[协议层]CDN 4.[协议层]反向代理负载均衡 5.[网络层]IP负载均衡 面试题3:你平时是怎样定位线上问题的? 总结 面试题1:当你发现一条SQL很慢,你的处理思路是什么? 发现Bug 确定Bug不是自己造成的,如果无法确定,不要理会步骤1 向组内宣传"程序里有一个未知Bug,错不在我" 谁响应,谁对Bug负责 没人响应,就要求特定人员配合调试 如果不配合

  • Java面试题冲刺第一天--基础篇1

    目录 面试题1:Java 中操作字符串都有哪些类?它们之间有什么区别? 正经回答: 深入追问: 追问1:这三者在效率上怎么说? 追问2:那StringBuffer和StringBuffer线程安全主要差在哪里呢? 面试题2:请你说一下Error 和 Exception 区别是什么? 正经回答: 面试题3:== 和 equals 的区别是什么 正经回答: 深入追问: 追问1:如果我们不重写equals() 方法,会怎么样? 追问2:重写equals的同时,我们需要重写hashCode()方法么?为

  • Java面试题冲刺第二十二天-- Nginx

    目录 面试题1:谈一下你对 Nginx 的理解 为啥我们总说Nginx好用? 追问1:正向代理和反向代理区别在哪? 正向代理 面试题2:常用的 Nginx 做负载均衡的策略有哪些? 1.指定权重(weight)轮询(默认,常用): 2.ip_hash(常用): 3.least_conn: 4.fair(第三方) 面试题3:说几个你常用的 nginx 命令吧 总结 面试题1:谈一下你对 Nginx 的理解 Nginx 是一款自由的.开源的.高性能的 HTTP 服务器和反向代理服务器:同时也是一个

  • Java面试题冲刺第二十四天--并发编程

    目录 面试题1:说一下你对ReentrantLock的理解? CAS: AQS: 追问1:你认为 ReentrantLock 相比 synchronized 都有哪些区别? 面试题2:解释一下公平锁和非公平锁? 面试题3:能详细说一下CAS具体实现原理么? 追问1:那CAS的缺陷有哪些呢? 1.ABA: 2.自旋消耗资源: 3.多变量共享一致性问题: 追问2:讲一下什么是ABA问题?怎么解决? 总结 面试题1:说一下你对ReentrantLock的理解? ReentrantLock是JDK1.5

  • Java面试题冲刺第二十五天--并发编程3

    目录 面试题1:你了解线程池么?简单介绍一下. 追问1:连接池 和 线程池是一个意思么?有什么区别? 不同点 面试题2:线程池中核心线程数量大小你是怎么设置的? 追问1:核心线程数量过大或过小会造成什么后果? 面试题3:线程池都有哪些状态呀? 追问1:什么条件下会进入TERMINATED状态 总结 面试题1:你了解线程池么?简单介绍一下. java提供的一个java.util.concurrent.Executor接口的实现用于创建线程池. 线程池是一种多线程处理形式,处理过程中将任务提交到线程

  • Java面试题冲刺第二十五天--JVM2

    目录 面试题1:简单说一下java的垃圾回收机制. 面试题2:JVM会在什么时候进行GC呢? 追问1:介绍一下不同代空间的垃圾回收机制 追问2:能说一下新生代空间的构成与执行逻辑么? 追问3:说一下发生OOM时,垃圾回收机制的执行流程. 面试题3:Full GC .Major GC和 Minor GC有什么不同 (1)Minor GC / Young GC (2)Old GC (3)Full GC (4)Major GC (5)Mixed GC 总结 面试题1:简单说一下java的垃圾回收机制.

随机推荐