redis10大面试题

1.简介以及优点

Redis简单说就是一个数据库,与传统数据库不同的是数据存在内存中,所以存写速度非常快,redis支持事务,持久化,lua脚本,多种集群方案。

2.Redis的数据类型应用场景

1)string: 简单的key-value型
2)Hash: 适合存储对象,如:用户信息,商品信息
3)List: 链表,可以存储粉丝列表,消息列表,双向链表,额外的内存开销
4)Set 集合,主要适合求交集、并集、差集的场景,如共同好友,共同爱好
5)Sorted set 有序集合,多个一个权重,适合有集合属性又有排序的功能,如排行榜

3.Redis和memcache的区别

1)redis数据类型多,支持数据持久化,原生支持持久化
2)Memcache是多线程,非阻塞IO多路复用的网络模型,redis单线程多路IO复用模型,redis支持事务

4.Redis设置过期时间的过期删除策略

使用场景:短信验证码,添加一个过期时间
删除策略:定期删除+惰性删除
定期删除:redis默认100ms随机抽取一定数量的key判断是否删除
惰性删除:是靠用户访问某个key 如果key存在就去判断是否过期,是不是很懒,如果这个key这两种删除都没有命中,就会一直留在内存中,什么时候删除呢,请看下边的redis内存淘汰机制。

5.Redis内存淘汰机制

· volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最久使用的数据淘汰
· volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
· volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
· allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最久使用的key(这个是最常用的).
· allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
· no-eviction:禁止驱逐数据,也就是说当内存不足以容纳新写入数据时,新写入操作会报错。这个应该没人使用吧!
一般会选择allkeys-lru
redis4.0后新增:
lfu: 最近使用次数很少的key
· volatile-lfu:在设置了过期时间的key中使用LFU算法淘汰key
· allkeys-lfu:在所有的key中使用LFU算法淘汰数据

6.Redis持久化机制

RDB:快照备份,在单位时间里有X个key发生了变化,出发rdb备份,fork一个进程,把内存中的数据生成一个rdb文件,替换掉之前的rdb文件
Aof:追加文件模式,把增,删,改操作追加写入aof文件,策略有1)每次更改,2)每秒更改,3)根据机器的心情, 居中策略选择每秒。 aof有个配置为定期重新归整aof文件,这样可以瘦身aof文件。也可以手动执行命令归整aof文件
既然有两种持久化策略,如果重启,会如何选择呢? 如果两种机制都开启了(建议都开启),会优先选择aof(原因是aof的数据比较全),但是rdb恢复速度会大于aof

7.Redis事务

1)redis支持事务的一个原因是redis是单线程执行
2)Redis事务不保证原子性,不保证原子性:redis同一个事务中如果有一条命令执行失败,其后的命令仍然会被执行,没有回滚
3)执行流程
开启:以MULTI 开启一个事务
入队:将多个命令入队到事务中,接到这些命令不会立即执行,而是放到等待执行的事务队列里面
执行:由EXEC命令触发事务

8.Redis常见问题(缓存击穿,穿透和雪崩)及解决方案

击穿:为用户刚好访问一个热点key,此key刚好失效,导致大量用户访问到数据库
穿透:用户传很多缓存里没有的key,如果没有做保护措施,也同样会导致大量用户访问到数据库
雪崩:大批量的key在同一时间失效,导致大量用户访问到数据库
解决方案:
击穿:这个一般出现在热点事件(XXXXX),这块可以手动设置一个很大的过期日期,也要做好保护措施,只让一个用户到数据库库读数据,然后写入缓存,redis锁实现
穿透:最直接的就是不管用户传什么key,我们都缓存到redis里,还有就是加数据校验,控制在某个区域里的key才是正确的
雪崩:一般出现在批量数据生成缓存时,我们一般加一个随机数来保证不会在同一时间导致key失效

9.缓存和数据库双写一致性

正常操作,先删除缓存,再修改数据库然后写入redis,一般是没问题,但是请求量大就不能保证不会在修改数据库和写入redis期间,其他用户把旧的数据写入redis。
解决方案:

  1. 修改了配置文件是先淘汰缓存还是先写表
    1)假设先写数据库,再淘汰缓存:第一步写数据库操作成功,第二步淘汰缓存失败,则会出现DB中是新数据,Cache中是旧数据,数据不一致
    2)假设先淘汰缓存,再写数据库:第一步淘汰缓存成功,第二步写数据库失败
    结论:先淘汰缓存,再写数据库。
  2. 数据不一致原因
    第一种情况肯定会出现数据不一致
    关键分析第二种
    1)A用户修改配置,清空cache,去修改数据库
    2)这时B用户过来查看cache为空,去读取数据库,A用户还没修改完,此时B用户读取的为脏数据,并且写入了缓存,
    3)由于A用户和B用户修改和读取的时间差,导致了数据的不一致
  3. 解决方案:
    1)A用户修改配置,清空cache,setnx一个值(设置一个过期时间),然后去修改数据库,修改成功或失败后,删除setnx的key
    2)这时B用户过来查看cache为空,先看下setnx是否成功,失败代表正在修改数据库,成功后获取数据,写入缓存,删除setnx的key
    参考链接:https://blog.csdn.net/yilukuangpao/article/details/103035277

10.Redis基本数据结构实现

来源:https://www.jianshu.com/p/942a47f7318d
1.字符串:采用预分配冗余空间的方式来减少内存的频繁分配
在这里插入图片描述
链表:
Redis将列表数据结构命名为list而不是array,是因为列表的存储结构用的是链表而不是数组,而且链表还是双向链表。因为它是链表,所以随机定位性能较弱O(n),首尾插入删除性能较优O(1)。如果list的列表长度很长,使用时我们一定要关注链表相关操作的时间复杂度。

快速列表
在这里插入图片描述
如果再深入一点,你会发现Redis底层存储的还不是一个简单的linkedlist,而是称之为快速链表quicklist的一个结构。
首先在列表元素较少的情况下会使用一块连续的内存存储,这个结构是ziplist,也即是压缩列表。它将所有的元素紧挨着一起存储,分配的是一块连续的内存。当数据量比较多的时候才会改成quicklist。因为普通的链表需要的附加指针空间太大,会比较浪费空间。比如这个列表里存的只是int类型的数据,结构上还需要两个额外的指针prev和next。所以Redis将链表和ziplist结合起来组成了quicklist。也就是将多个ziplist使用双向指针串起来使用。这样既满足了快速的插入删除性能,又不会出现太大的空间冗余。
3.哈希hash
hash 的实现类似java的HashMap。
它使用二维结构,第一维是数组,第二维是链表,hash的内容key和value存放在链表中,数组里存放的是链表的头指针。通过key查找元素时,先计算key的hashcode,然后用hashcode对数组的长度进行取模定位到链表的表头,再对链表进行遍历获取到相应的value值,链表的作用就是用来将产生了「hash碰撞」的元素串起来,也就是拉链法解决hash冲突问题。哈希的第一维数组的长度也是2^n。
在这里插入图片描述
4.集合set
类似java的HashSet的内部实现使用的是HashMap。Redis的set结构也是一样,它的内部也使用hash结构,所有的value都指向同一个内部值。
5.有序集合 sorted set
redis 的 zset 是一个复合结构,第一个是hash,第二个是跳跃列表skiplist。hash 结构来存储 value 和 score 的对应关系,保障元素value的唯一性,可以通过元素value找到相应的score值。跳跃列表的目的在于给按照score排序,根据score的范围获取value列表。
在这里插入图片描述

11. redis 锁

  互斥性。在任意时刻,只有一个客户端能持有锁。
  不会发生死锁。即使有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁。
  具有容错性。只要大部分的Redis节点正常运行,客户端就可以加锁和解锁。
  解铃还须系铃人。加锁和解锁必须是同一个客户端,客户端自己不能把别人加的锁给解了
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yilukuangpao

你的鼓励是我创造最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值