前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java高频面试题- 每日三连问?【Day1】 — Redis篇

Java高频面试题- 每日三连问?【Day1】 — Redis篇

作者头像
浩说编程
发布2021-08-17 17:41:11
5580
发布2021-08-17 17:41:11
举报
文章被收录于专栏:Java经验之谈

问题导读

一、你在哪些应用场景用到了Redis?

二、Redis都支持哪些数据类型?

追问-1:在业务中如何选择要用的数据类型?

三、聊一下对缓存穿透、缓存击穿、缓存雪崩的理解吧?

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

01

你在哪些业务场景用到了Redis ?

正经回答:

1、计数器

可以对 String 进行自增自减运算,从而实现计数器功能。Redis 这种内存型数据库的读写性能非常高,很适合存储频繁读写的计数量。

2、缓存

将热点数据放到内存中,设置内存的最大使用量以及淘汰策略来保证缓存的命中率。

3、会话缓存

可以使用 Redis 来统一存储多台应用服务器的会话信息。当应用服务器不再存储用户的会话信息,也就不再具有状态,一个用户可以请求任意一个应用服务器,从而更容易实现高可用性以及可伸缩性。

4、分布式锁实现

在分布式场景下,无法使用单机环境下的锁来对多个节点上的进程进行同步。可以使用 Redis 自带的 SETNX 命令实现分布式锁,除此之外,还可以使用官方提供的 RedLock 分布式锁实现。

5、其它

Set 可以实现交集、并集等操作,从而实现共同好友等功能。ZSet 可以实现有序性操作,从而实现排行榜等功能。

02

Redis都支持哪些数据类型?

正经回答:

Redis主要有5种数据类型,包括String,List,Set,Zset,Hash。

数据类型

可以存储的值

操作

应用场景

STRING

字符串、整数或者浮点数

对整个字符串或者字符串的其中一部分执行操作对整数和浮点数执行自增或者自减操作

做简单的键值对缓存

LIST

列表

从两端压入或者弹出元素对单个或者多个元素进行修剪,只保留一个范围内的元素

存储一些列表型的数据结构,类似粉丝列表、文章的评论列表之类的数据

SET

无序集合

添加、获取、移除单个元素检查一个元素是否存在于集合中计算交集、并集、差集从集合里面随机获取元素

交集、并集、差集的操作,比如交集,可以把两个人的粉丝列表整一个交集

HASH

包含键值对的无序散列表

添加、获取、移除单个键值对获取所有键值对检查某个键是否存在

结构化的数据,比如一个对象

ZSET

有序集合

添加、获取、删除元素根据分值范围或者成员来获取元素计算一个键的排名

去重但可以排序,如获取排名前几名的用户

深入追问:

追问-1:在业务中如何选择要用的数据类型?

  • string:适合最简单的k-v存储,类似于memcached的存储结构,短信验证码,配置信息等,就用这种类型来存储。
  • hash:般key为ID或者唯一标示,value对应的就是详情了。如商品详情,个人信息详情,新闻详情等。
  • list:因为list是有序的,比较适合存储一些有序且数据相对固定的数据。如省市区表、字典表等。因为list是有序的,适合根据写入的时间来排序,如:最新的***,消息队列等。
  • set:可以简单的理解为ID-List的模式,如微博中一个人有哪些好友,set最牛的地方在于,可以对两个set提供交集、并集、差集操作。例如:查找两个人共同的好友等。
  • Sorted Set:是set的增强版本,增加了一个score参数,自动会根据score的值进行排序。比较适合类似于top 10等不根据插入的时间来排序的数据。

03

聊一下对缓存穿透、缓存击穿、缓存雪崩的理解吧

正经回答:

  • 缓存穿透:指缓存和数据库中都没有的数据,导致所有的请求都打到数据库上,然后数据库还查不到(如null),造成数据库短时间线程数被打满而导致其他服务阻塞,最终导致线上服务不可用,这种情况一般来自黑客同学。
  • 缓存击穿:指缓存中没有但数据库中有的数据(一般是热点数据缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去查,引起数据库压力瞬间增大,线上系统卡住。
  • 缓存雪崩:指缓存同一时间大面积的失效,缓存击穿升级版。

深入追问:

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

  1. 根据实际业务情况,在Redis中维护一个热点数据表,批量设为永不过期(如top1000),并定时更新top1000数据。
  2. 加互斥锁(mutex key)

互斥锁 缓存击穿后,多个线程会同时去查询数据库的这条数据,那么我们可以在第一个查询数据的请求上使用一个互斥锁来锁住它。

其他的线程走到这一步拿不到锁就等着,等第一个线程查询到了数据,然后做缓存。后面的线程进来发现已经有缓存了,就直接走缓存。

代码语言:javascript
复制
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三个问题,你做到心中有数了么?

对了,如果你的朋友也在准备面试,请将这个系列扔给他,如果他认真对待,肯定会感谢你的!!

好了,今天就到这里,学废了的同学,记得三连,也会给我继续更新的动力。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-07-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 浩说编程 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 正经回答:
  • 正经回答:
  • 深入追问:
    • 追问-1:在业务中如何选择要用的数据类型?
    • 正经回答:
    • 深入追问:
      • 追问1:那你说一下针对缓存击穿的解决方法
      • 每日小结
      相关产品与服务
      云数据库 Redis
      腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档