redis-面试题

什么是Redis?

一种key-value类型的非关系数据库,他是基于内存的操作,所以他的速度很快。

Redis的数据类型?

常用的五种分别是,String,Hash,List,Set,Zet

String:一般用在seesion共享,分布式事务,或者mq的ack版本号

Hash:对业务中的数据做缓存,如把user中姓名为张山的整体数据做缓存可以用hash

List:双向链表的形式,可以做MQ消息发布失败时候,存放在list采用Lpush头插入,rpush尾插

set:无序不重复,用在好友添加,相同的好友只允许添加一次

zset:有序不重复,用在排行榜

Redis的过期策略?

一共三种:

​ 1.对于设置了定时的key,各自开启一个定时器。称为定时过期策略。占用资源相当于每个key携带了一个定时器。

​ 2.设置一个时间段,全局定时器,在某个时间遍历一定设置了过期时间的key进行删除。

​ 3.每当访问一个设置有过期时间的key,先查看key是否过期,会导致大量的key过期但是没有被访问,一直存在内存中。

Radis过期策略?

一共8中其中六种使用了算法,LRU,LFU,和随机,

LRU:最近最少访问,分别时对所以key,和过期时间的key。

LFU:最少访问,同LRU。

random:随机从全部key删除,从过期时间的key删除。

另外俩种:一种是,对于过期时间的key,过期时间设置越早的被淘汰,另一种,默认,不会删除key,内存不足报错。

Redis的缓存击穿,缓存穿透,缓存雪崩?

拿缓存击穿来说,导致它的原因是一个key在它刚刚过期的时候,大量的请求正好访问它,从而导致直接访问到数据库。

为了解决它,可以使用互斥锁setnx去操作,如果有就返回1,没有就创建返回0。或者设置key不过期。

然后和缓存击穿类似的也可以说缓存击穿是他的一小部分,缓存雪崩,大量的key失效,导致大量的请求发送到数据库,可能会导致数据库宕机。解决办法设置过期时间可以通过一个范围的随机数,可能发生把他降到缓存击穿。

而缓存穿透是一个缓存没有的值,这就会导致查询数据库,比如缓存有1,数据库有1,因为操作失误都被删除,一直用1访问,解决办法,就是在缓存中添加一个默认值或者空值。

什么是热点Key?

用户消费的数据大于生产的数据,秒杀,热点。

解决可以扩容,把热点key分布到多个redis中。

redis中的持久化优缺点?

redis中的持久化有俩种,一种是RDB,一种是AOF。

RDB:执行在AOF后

俩种触发:手动和自动,

保存方式:以快照的形式进行存放在指定的目录下生成一个,dump.rdb。

默认:是。

优点:可以进行大量的备份,大规模的数据恢复。

缺点:无法保证数据的实时性的一致性。

AOF:执行在最开始

保存方式:通过保存操作指令来进行数据备份。

默认:不是。

优点:保证数据的一致性。

缺点:随着数据的增加会越来越大。

redis怎么实现分布式锁?

通过setnx和expire来实现,当一个事务执行的时候,通过setnx来判断是否存在,存在进行设置过去时间。

使用redisssion,redisson中有看门狗这个概念,就是每十秒去查看锁是否还被持有,有就增加过去时间。

redis和mysql怎么保证双写的一致性?

redis进行双删,当一个更新请求进来,先删除缓存在更新数据库,在删除

redis中的事务?

不是acid,他是顺序,一次,排他,通过muitl开启事务,exec 执行, discard撤销。

redis解决hash冲突?

和hashmap一样采用链哈希法,将想同的hash值的key通过next进行指向,每次查询就查询哈希链表

redis和mysql怎么解决数据一致性?

在设计的时候符合这三步。
命中:先从缓存查找数据,命中,直接返回。
失效:先从缓存查找数据,没有,进入数据库,成功之后放到缓存中。
更新:先更新数据库,删除缓存

为什么先更新数据库在删除?

举例:

第一种先更新缓存在更新数据库

线程A 对带着一条数据(age=22)走来了,经过特别复杂的业务处理浪费了好几个秒,更新到了redis中。然后开心的去找数据库,此时,在填入数据库的过程回滚!当然你也可以开启redis的事务进行回滚,但是浪费的时间,这是对整体是不友好的。

第二种先更新数据库,在更新缓存。

线程A带着数据(age=22)走向了数据库,更新完了,正要更新redis之前,线程B带着数据(age=23)去了数据库,可能是因为B比较圆润,执行的比较快,更新完了数据库(age=23)更新缓存(age=23),此时的A,更新缓存(age=22)。那我最新的数据23没有了!

第三种先删除缓存在更新数据库

线程A(age=22)把缓存删掉,去更新数据库的时候,线程B读取age发现没有,直接跑到数据库拿到了旧的数据(age=21),加入缓存中。线程A更新数据库(age=22),而缓存中的是(age=21)。

第四种先更新数据库,在删除缓存

线程A(age=22)更新到数据库,缓存中是(age=21)把他删掉,如果在线程B读取的时候,线程A没有执行删除缓存,线程B就以命中的形式,不会查找数据库,此时的线程A删除缓存,下回查询以失效的形式进行添加到缓存。

第五种先更新数据库,等一会删除缓存

为什么这么做,线程A在读取缓存的时候,失效,去数据库查找并存入缓存的过程中,线程B的更新数据库和删除缓存比线程A快了一步,导致线程B并没有将线程A更新到缓存中的数据删掉。缓存中一直存放这旧数据。我们可以在删除缓存的时候让他小睡一会。也就是所谓的延时删除。

第六种双删/延迟双删

和第五种对比,
第六种查询次数:
线程A还没有更新数据库,线程A删除了缓存,线程B查询缓存没有,查数据库。还是旧数据。1次缓存1次数据库。
线程A更新了数据库,删除缓存延时。线程C读取到了缓存还是旧数据。1次缓存。
线程A流程执行完,线程D读取缓存没有,查找数据库,填入缓存。1次缓存,1次数据库。
查找了3次缓存,2次数据库。
第五种;
线程A还没有更新数据库,线程B查询命中缓存。旧数据。1次缓存
线程A更新了数据库,删除缓存延时。线程C读取到了缓存还是旧数据。1次缓存
线程A流程执行完,线程D读取缓存没有,查找数据库,填入缓存。1次缓存1次数据库。
总结:相比双删的情况下,先更新在删除会减少一次数据库连接,相差不大。
这些都是在单体下不是高并发,
集群下考虑的话,就要加入阿里的canal,实现mysql的binlog文件订阅,达到一致性,也会有有问题,redis突然挂掉,还得考虑重复添加,引入MQ,如果多线程下又不能保持数据的顺序性,最好就是单线程下执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值