Redis面试汇总笔记
在两个月前的学习中,我看过一个redis相关的讲解视频,是一个叫诸葛的老师,其中分为几层进行讲述,分别是数据类型、分布式锁、redis常见问题等。当时有记录一些内容,下面将按照顺序进行分享。
(一)常见的数据类型
结合视频的内容,通过一张结构图来展示各个数据类型之间的关系:
常见的数据类型一般都是图上的几种:String、Hash、List、Set、有序集合Set。
(1)String
常用操作:
1)字符串常用操作
set key value;
mset key valye [key value …]; //批量存储字符串键值对
setnx key value; //存入一个不存在的字符串键值对
get key [key …];
del key [key …];
expire key seconds //设置一个键的过期时间
2)原子加减
incr key //将key中存储的数字加1
decr key //将key中存储的数字减1
incrby key increment //将key所存储的值加上increment
decrby key decrement //将key所存储的值减去decrement
3)分布式锁
setnx [key] true //返回1代表取锁成功,返回0代表获取锁失败
del [key] //释放锁,即删除锁
set [key] true ex 10nx //防止程序意外终止导致死锁,即设置过期时间
同时还可以存储对象数据,不过需要将对象数据转Json数据格式。
应用场景:
1)计数器
incr article:readcount:{文章id} //针对文章id的阅读值,做原子性的+1操作
get article:readcount:{文章id} //获取阅读数
2)分布式系统全局序列号
increby orderid 100 //redis批量生成序列号提升性能
解释:一次操作取100个编号,利用自增部分来使用编号。从性能角度分析,原来是操作100次redis进行取值,现在只需要操作一次,从而实现性能提升。
(2)Hash
常用操作:
hset key field value //存储一个hash表key的值
hsetnx key key field value //存储一个不存在的hash表的值
hmset key field value [field value …] //在一个哈希表中存储多个键值对
hget key field //获取哈希表中key对应的field键值
hmget key field [key field …] //批量获取哈希表中的key对应的多个field键值
hdel key field [field …] //删除
hlen key //返回哈希表中key对应的field的数量
hgetall key //返回哈希表中key中所有的键值
hincrby key field increment //为哈希表中的key的field键的值加上增量increment
应用场景:
1)电商购物车
①以用户id为key
②商品id为field
③商品数量为value
2)购物车操作
①添加商品->hset cart:1001 10088 1
②增加数量->hincrby cart:1001 10088 1
③商品总数->hlen cart:1001
④删除商品->hdel cart:1001 10088
⑤获取购物车所有商品->hgetall cart:1001
(3)List
常用操作:
lpush key value [value …] //将一个或多个值value插入key列表的表头(最左边)
rpush key valye [value …] //将一个或多个值value插入key列表的表胃(最右边)
lpop key //移除并返回key列表的头元素
rpop key //移除并返回key列表的尾元素
lrange key start top //返回列表key中指定区间内的元素,区间以偏移量start和stop指定。(分正向索引和负向索引)
blpop key [key …] timeout //从key列表表头弹出一个元素,若列表中没有元素,阻塞等待timeout秒,如果timeout=0,一直阻塞等待
brpop key [key …] timeout //从key列表表尾弹出一个元素,若列表中没有元素,阻塞等待timeout秒,如果timeout=0,一直阻塞等待
常用的分布式数据结构:
Stack(栈) = lpush + lpop = FILO
Queue(队列) = lpush + rpop = FIFO
Blocking MQ(阻塞队列) = lpush + brpop
应用场景:
1)微博和微信公众号消息流
诸葛老师关注了Caoz,备胎说车等大V。
①CaoZ发微博,消息id为10018
lpush msg:{诸葛老师-ID} 10018
②备胎说车发微博,消息id为10086
lpush msg{诸葛老师-id} 10086
③查看最新微博消息
lrange msg:{诸葛老师-id} 0 4
解释:可能存在关注同一个人,但是接收到新推送的消息存在延迟,因为底层实现排队发送,比如优先发送在线人员,在发送不在线的。
(4)Set
常用操作:
(后续补充)
应用场景:
1)抽奖程序(微信小程序等)
2)微信微博点赞、收藏、标签
3)集合操作实现电商商品筛选
集合的运算(实现关注模型)
1)交集
{a,b,c} {a,c} => {a,c}
2)差集
{a,b,c} {b,d,f,g} => {a,c}
3)并集
{a,b,c} {c,d,f,g} => {a,b,c,d,f,g}
(5)有序Set
常用操作:
(后续补充)
应用场景:
1)实现热榜排行前十等
底层实现结构:
1)压缩列表
(后续补充)
2)跳表
当压缩列表达到一个大小时,会从压缩列表转化为跳表。跳表结构有点类似mysql底层数据结构,B+tree,即冗余排好序的序号作为结点头部,利用多路查询树的结构进行设计。
(二)分布式锁
(1)基于原生的redis命令setnx
在redis中,基于setnx命令的操作,就可以实现分布式锁相关业务,与在Java中的redistemplate中是使用setIfAbsent是一致的。
(2)基于redission组件
该组件就是基于一系列的分布式场景设置了许多类型的锁,比如基础的同步锁,读写锁等,读者可以自行探讨。
分布式锁的设计理念:
①对缓存内存进行设置(单值设置,如果存在多个线程进行设置时,只有一个线程能设置成功,其他线程失败);
②设置缓存失效时间;(解决因程序出错,导致死锁的问题)
③通过lua代码实现一个锁续命操作,底层成为看门狗,负责检测当前锁是否失效,如果没有,则重新设置锁的过期时间;注:lua代码的执行是一个原子性操作,意味着有么就全部操作正常,要么就全部操作失败;(确保原子性)
(三)缓存问题
当业务代码涉及到先查询缓存,如果存在,则取出redis中的缓存值,并且返回,否则查询数据库,取到对应内容,再设置到缓存中,并且返回,此时就会出现下述前三个问题。
(1)缓存击穿(缓存失效)
解释:也叫热点Key问题,就是一个被高并发访问并且缓存重建业务较复杂(意味着对数据库压力相对较大)的key突然失效了,无数的请求访问会在瞬间给数据库带来巨大的压力,导致数据库服务挂掉(可以理解为redis的缓存暂时没有,此时高并发情况下,所有线程进到接口时,都会判断当前redis缓存不存在,因此会有大量的请求访问数据库)。
解决方法:
1、互斥锁:当同个业务不同线程访问redis未命中时,先获取一把互斥锁,然后进行数据库操作,此时另外一个线程未命中时,拿不到锁,等待一段时间后重新查询缓存,此时之前的线程已经重新把数据加载到redis之中了,线程二就直接缓存命中。这样就不会使得大量访问进入数据库。
(2)缓存穿透
解释:有一个商品被删掉了,但是在高并发情况下,首先去检查缓存,此时发现缓存没有,就去查询数据库,此时还是查询不到,然后就返回不了任何数据。
解决方案:当查询到数据库发现不存在时,可以设置一个空值,就可以避免所有请求直接访问数据库,减轻数据库压力。
(3)缓存雪崩
解释:当缓存在同一时间内大部分失效,此时导致所有的请求访问接口时,会同时访问数据库,造成数据库服务访问压力过大。
解决方法:在设置过期时间时,利用固定时间+随机数时间进行设置,避免同一时间大面积缓存失效。
(4)缓存和数据库双写不一致的问题
(后续补充)
(5)缓存数据冷热分离
解释:由于redis的资源有限,不可能将所有的数据都防止缓存中,因此只需要装热数据缓存在redis中即可,冷数据失效。具体实现原理为设置缓存过期时间即可。
Redis面试汇总笔记相关推荐
- python运维开发招聘_GitHub - PlutoaCharon/LiunxNotes: 校招-运维开发(Liunx,Python,Golang)面试学习笔记...
校招-运维开发(Liunx,Python,Golang)面试学习笔记 1. 网络基础类 2. Linux系统管理类 3. Linux服务管理类 4. 数据库管理 索引(包括分类及优化方式,失效条件 ...
- Java程序员必备!Redis面试复习大纲在手面试不慌
咱先来聊聊Redis 像Redis的基础入门,掌握下图这几个列出来的知识点足以了. 进阶的话,就得下点功夫了,事务.主从复制.哨兵.集群等等之类的搞不明白你就上不去呀. 再看美团亿级流量Redis实战 ...
- Redis面试复习大纲在手面试不慌,内含福利
前言 这几年在Java工程师招聘时,会看到很多人的简历都写着使用了Spring Cloud做微服务实现,使用Docker做自动化部署,并且也会把这些做为自己的亮点.而比较有趣的这其中以小公司出来的人为 ...
- Java后端技术面试汇总(第一套)
面试汇总,整理一波,doc文档可点击[ 此处下载] 1.基础篇 1.1.Java基础 • 面向对象的特征:继承.封装和多态 • final, finally, finalize 的区别 • Excep ...
- Redis 分布式锁笔记
Redis 分布式锁笔记 (公众号:水滴与银弹)深度剖析:Redis分布式锁到底安全吗? 一.初识分布式锁 1.什么是分布式锁 分布式环境下,我们在写多线程程序时,避免同时操作一个共享变量产生数据 ...
- 前端面试+学习笔记(HTML+CSS+JavaScript+ES6+Vue+NodeJs)
前端面试+学习笔记(HTML+CSS+JavaScript+ES6+Vue+NodeJs) 一. HTML 1. 盒子模型 是什么:每个元素被表示为一个矩形的盒子,有四个部分组成:内容(content ...
- 用友Java面试汇总
用友Java面试汇总 春招实习 参考意义不大 昨天晚上接到了用友的电话,让我订时间,约好今天1点30 1点40开始电话面试 (1)自我介绍,根据情况进行一些简单提问,例如问了我做项目的感受是什么,进入 ...
- Java开发西安地区最近面试汇总(三)
Java开发西安地区最近面试汇总(三) 1.Spring的循环依赖 构造器的循环依赖 案例 结论 属性的循环依赖 案例 结论 Spring内部是在何时完成的属性注入,又是如何解决的循环依赖. 小结 2 ...
- Java面试汇总>>>初级工程师—面试1000题
面试汇总>>> 每日刷题 001:重载和重写有什么区别?阐述二者是什么? 002:什么是线程池?线程池有什么优点? 003:线程有几种状态,他们是怎么切换的呢? 004:比较一下St ...
最新文章
- c 输出中文乱码_pandas常用函数学习,从文件读取输出过程中学会处理数据
- “数据科学家”或许不再性感,但“数据团队”的产业化才刚开始 | 专访领英全球数据科学团队负责人...
- 飞得更高:(三)人不好招啊
- 【操作】鼠标hover效果——元素凸起并产生阴影
- Hashtable与Dictionary
- leetcode 无重复字符的最长子串
- hnust 神奇的序列
- 20145335 《信息安全系统设计基础》第2周学习总结
- Java的代码书写规范
- 2018年全球智能手机销售收入增至5220亿美元 但销量却下降了
- 相比 C 、C++,Go 为什么不火?
- 工具安装----Clang-format的基本使用
- excel VBA编程入门教程
- Spotfire 使用IronPython脚本
- 2020长安杯网站重构
- eclipse 打开jsp页面卡死问题
- 细胞器基因组|比较基因组分析助力深度挖掘细胞器进化关系
- 没经验能做seo专员吗
- was连接oracle rac集群,oracle 11g rac 集群操作命令
- CentOS7 配置R语言及Rstudio-serve
热门文章
- 学生用计算机玩游戏怎么按OK键,玩电脑游戏是怎么切换桌面
- 2023上海车展-座舱技术趋势:屏幕多元化、汽车声学、AR-HUD、元宇宙座舱...
- 驾考宝典*科目一+四*经验备份分享*仅供参考
- mondrian olap 示例_java开源的OLAP引擎--mondrian
- 广东电信IPTV机顶盒HG680-J私人定制过程
- linux 内核配置sdio,linux SDIO实现
- 技巧分享:你知道视频转文字怎么操作?
- 深度学习玩LOL-游戏助手-概述
- 应届毕业生找工作应该学习的
- Nutanix与联想因MSP再结缘,共赴混合云之约