Redis常问八股

1.sortedSet底层

sortedset中的每一个元素都带有一个score属性可以基于score属性对元素进行排序,底层的实现是一个跳表加hash表。

可排序元素不重复

查询速度快

2.NoSQL和SQL

SQL

1对数据的格式有严格的约定
Table必须定义每个属性的数据格式
每个Table必须含有主键
只能存储Table格式的数据
2允许Table之间建立联系
支持不同Table之间建立一对一、一对多、多对一、多对多的关系
支持Join操作来基于关系进行联合查询
3有统一的查询语言
所有的关系型数据库都支持基于SQL的查询语言
NoSQL

对数据格式没有约束
可以存储文档、图、Key-Value等等
每个存储对象是一个集合,集合内的元素可以是各种形式
数据之间一般没有或只有很少的关联
没有统一的查询语言,每个数据库都会提供自己的API接口

3.缓存穿透

缓存穿透:查询一个不存在的数据, mysql 查询不到数据也不会直接写入缓存,就会导致每次请求都查数据库

解决方案

1.缓存空数据,查询返回的数据为空,仍把这个结果进行缓存

2.布隆过滤器

什么是布隆过滤器

布隆过滤器主要是用于检索一个元素是否在一个集合中。我们当时使用的是redisson实现的布隆过滤器。
它的底层主要是先去初始化一个比较大数组,里面存放的二进制0或1。在一开始都是0,当一个key来了之后经过3次hash计算,模于数组长度找到数据的下标然后把数组中原来的0改为1,这样的话,三个数组的位置就能标明一个key的存在。查找的过程也是一样的。
当然是有缺点的,布隆过滤器有可能会产生一定的误判,我们一般可以设置这个误判率,大概不会超过5%,其实这个误判是必然存在的,要不就得增加数组的长度,其实已经算是很划分了,5%以内的误判率一般的项目也能接受,不至于高并发下压倒数据库。

4.缓存击穿

缓存击穿的意思是指某一热点数据存储到Redis中,该数据处于并发场景下,如果此时该key过期失效,这样就会有大量并发请求进入数据库,对数据库产生巨大压力甚至压跨数据库。

解决方案:

第一可以使用互斥锁:当缓存失效时,不立即去load db,先使用如 Redis 的 setnx 去设置一个互斥锁当操作成功返回时再进行load db的操作并回设缓存,否则重试get缓存的方法

setnx


第二种方案可以设置当前key逻辑过期,大概是思路如下:


①:在设置key的时候,设置一个过期时间字段一块存入缓存中,不给当前key设置过期时间
2):当查询的时候,从redis取出数据后判断时间是否过期
3:如果过期则开通另外一个线程进行数据同步,当前线程正常返回数据,这个数据不是最新
当然两种方案各有利弊:
如果选择数据的强一致性,建议使用分布式锁的方案,性能上可能没那么高,锁需要等,也有可能产生死锁的问题
如果选择key的逻辑删除,则优先考虑的高可用性,性能比较高,但是数据同步这块做不到强一致。

5.什么是缓存雪崩

缓存雪崩意思是设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到DB,DB瞬时压力过重雪崩。与缓存击穿的区别:雪崩是很多key,击穿是某一个key缓存。

给不同的 Key 的 TTL 添加随机值
 利用 Redis 集群提高服务的可用性
 给缓存业务添加降级限流策略
 给业务添加多级缓存

6.缓存的更新策略

主动更新策略

1.Cache Aside Pattern用的最多

由缓存的调用者在更新数据库的同时更新缓存

2.Read/Write Through Pattern 

缓存与数据库整合为一个服务,由服务来维护一致性,调用者调用该服务无需关心缓存一致性问题

3.write behind caching pattern 

调用者只操作缓存,由其它线程异步的将缓存数据持久化到数据库保证最终一致

7.Redis持久化,哪种恢复快

RDB是一个快照文件,它是把redis内存存储的数据写到磁盘上,当redis实例宕机恢复数据的时候,方便从RDB的快照文件中恢复数据。
AOF的含义是追加文件,当redis操作写命令的时候,都会存储这个文件中,当redis实例宕机恢复数据的时候,会从这个文件中再次执行一遍命令来恢复数据

RDB因为是二进制文件,在保存的时候体积也是比较小的,它恢复的比较快,但是它有可能会丢数据,我们通常在项目中也会使用AOF来恢复数据,虽然AOF恢复的速度慢一些,但是它丢数据的凤险要小很多,在AOF文件中可以设置刷盘策略,我们当时设置的就是每秒批量写入一次命令

bgsave 开始时会 fork 主进程得到子进程,子进程共享主进程的内存数据。完成 fork 后读取内存数据并写入 RDB 文
件。
fork 采用的是 copy-on-write 技术:
• 当主进程执行读操作时,访问共享内存;
• 当主进程执行写操作时,则会拷贝一份数据,执行写操作

8.Redis的数据过期策略有哪些?

第一种是惰性删除,在设置该key过期时问后,我们不去管它,当需要该key时,我们在检查其是否过期,如果过期,我们就删掉它,反之返回该key。第二种是 定期删除,就是说每隔一段时间,我们就对一些key进行检查,删除里面过期的key定期清理的两种模式:
SLOW模式是定时任务,执行频率默认为10hz,每次不超过25ms,以通过修改配置文件redis.conf的 hz 选项来调整这个次数
FAST模式执行频率不固定,每次事件循环会尝试执行,但两次间隔不低于2ms,每次耗时不超过1ms
Redis的过期删除策略:惰性删除+定期删除两种策略进行配合使用。

9.Redis 数据淘汰策略

当 Redis 中的内存不够用时,此时在向 Redis 中添加新的 key ,那么 Redis 就会按照某一种规则将
内存中的数据删除掉,这种数据的删除规则被称之为内存的淘汰策略。
Redis 支持 8 种不同策略来选择要删除的 key :
 noeviction : 不淘汰任何 key ,但是内存满时不允许写入新数据,默认就是这种策略。
 volatile-ttl : 对设置了 TTL 的 key ,比较 key 的剩余 TTL 值, TTL 越小越先被淘汰
 allkeys-random :对全体 key ,随机进行淘汰。
 volatile-random :对设置了 TTL 的 key ,随机进行淘汰。
 allkeys-lru : 对全体 key ,基于 LRU 算法进行淘汰
 volatile-lru : 对设置了 TTL 的 key ,基于 LRU 算法进行淘汰
 allkeys-lfu : 对全体 key ,基于 LFU 算法进行淘汰
 volatile-lfu : 对设置了 TTL 的 key ,基于 LFU 算法进行淘汰

使用建议

优先使用 allkeys-lru 策略。充分利用 LRU 算法的优势,把最近最常访问的数据留在缓存中。如果业务有明显
的冷热数据区分,建议使用。
2. 如果业务中数据访问频率差别不大,没有明显冷热数据区分,建议使用 allkeys-random ,随机选择淘汰。
3. 如果业务中有置顶的需求,可以使用 volatile-lru 策略,同时置顶数据不设置过期时间,这些数据就一直不被删
除,会淘汰其他设置过期时间的数据。
4. 如果业务中有短时高频访问的数据,可以使用 allkeys-lfu 或 volatile-lfu 策略。

10.Redis分布锁如何实现

在redis中提供了一个命令setnx
由于redis的单线程的,用了命令之后,只能有一个客户端对某一个key设置值,在没有过期或删除key的时候是其他客户端是不能设置这个key的

如何实现分布锁的有效时长

redis的setnx指令不好控创这个问题,我们当时采用的reds的一个框架redisson实现的。
在redisson中需要手动加锁。并且可以控制锁的失效时间和等待时间。当锁住的一个业务还没有执行完成的时候,作redisson中引入了一个看门狗机制,就是说每隔一段时间就检查当前业务是否还持有锁,如果持有就增加加锁的持有时间,当业务执行完成之后需要使用释放锁就可以了
还有,个好处就是,在高并发下,业务有可能会执行很快。如果客户1有锁的时候。客户2来了以后并不会马上拒绝,它会不断尝试获取,如果客户1释放放之后,客户2可以马上有,性能得到了提升。

分布式锁可以重入吗

嗯,是可以重入的。这样做是为了避免死锁的产生。这个重入其实在内部就是判断是否是当前线程持有的锁。如果是当前线程持有锁就会计数,如果释放锁就会在计算上减一。在存储数据的时候采用的hash结构,大key可以按照自己的业务进行定制,其中小key是当前线程的唯一标识,alue是当前线程重入的次教

Redis实现主从一致性

MultiLock

11.Redis为什么被设计成单线程的

是因为最大限度地利用CPU缓存和避免多线程并发带来的锁争用,上下文切换等开销,从而实现更高的性能和最低的延迟此外采用异步I/O模型可以同时处理多个客户端请求进一步提高并发请求

12.如何保证Redis缓存双写一致

当修改了数据库的数据也要同时更新缓存的数据,缓存和数据库的数据要保持一致

Redis篇-详解双写一致_redis 双写一致-CSDN博客

13.Redis为什么那么快

l Redis 是纯内存操作,执行速度非常快
l 采用单线程,避免不必要的上下文切换可竞争条件,多线程还要考虑线程安全问题
l 使用 I/O 多路复用模型,非阻塞 IO

14.Redis集群有哪些方案?

在Redis中提供的集群方案总共有三种:主从复制、哨兵模式、Redis分片集群
主从同步
单节点Redis的并发能力是有上限的,要进一步提高Redis的并发能力,可以搭建主从集群,实现读写分离。一般都是一主多从,主节点负责写数据,从节点负责读数据,主节点写入数据之后,需要把数据同步到从节点中

15.redis集群脑裂,该怎么解决呢?

有的时候由于网络等原因可能会出现脑裂的情况,就是说,由于redismaster节点和redis salve节点和sentinel处于不同的网络分区,使得sentinel没有能够心跳感知到master,所以通过选举的方式提升了个salve为master,这样就存在了两个master,就像大脑分裂了一样,这样会导致客户端还在old master那里写入数据,新节点无法同步数据,当网络恢复后,sentinel会将oldmaster降为salve,这时再从新master同步数据,这会导致old master中的大量数据丢失。
关于解决的话,我记得在redis的配置中可以设置:第一可以设置最少的salve节点个数,比如设置至少要有一个从节点才能同步数据,第二个可以设置主从数据复制和同步的延迟时间,达不到要求就拒绝请求,就可以避免大量的数据丢失
  • 33
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值