Redis面试

redis数据类型

5.0之前5种:String、list、hash、set、zset
5.0之后新增了一种Stream流

zset的内存结构和原理

参考资料 https://www.bilibili.com/video/BV1BG4y197wV/?spm_id_from=333.788&vd_source=ec8146623a6d9ddb61ce61566ed2a56c

zset类型需要两个功能:
1、存储数据
2、进行排序
用来存储数据可以选择的数据结构是hash,用member当做key,score当做value。可以实现保存数据,但是无法进行排序;
跳表数据结构可以实现排序,但是无法实现用过member查询
因此redis,zset的数据结构就是既用了hash也用了跳表,同一个数据会存两份,一份存在hash,一份存在跳表。如果需要排序了,就用跳表,如果需要通过key查找了,就用hash。
存在的问题:占用空间,因为数据存了两份
在这里插入图片描述
在这里插入图片描述
当元素数量小于128并且每个元素都小于64字节时,采用压缩列表。不采用hash+跳表
这俩值,可以修改,但是一般不建议改。直接用默认就行
在这里插入图片描述

Redis数据结构

redis存储数据的方式类似hashmap,也是数组加链表的方式
底层存储数据的结构是bit[]

Redis pipeline

redis批量操作 大致原理
redis客户端执获取管道
发送命令-〉命令排队-〉命令执行-〉返回结果
在这里插入图片描述
在这里插入图片描述

redis为什么快

在这里插入图片描述
Redis内部结构是一张全局哈希表
在这里插入图片描述
redis初始化存储的容量是6,随着redis存入的数据增多,redis会进行扩容,称之为rehash,但是扩容的话就涉及元素 移动,影响性能,为了解决扩容带来的性能形象,进行了渐进式rehash
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

redis6.0之前为什么不适用多线程

在这里插入图片描述

redis6.0为什么引入多线程

在这里插入图片描述
根本原因是为了redis能抗住更大的并发

为什么要用 redis 而不用 map/guava 做缓存?(即为什么不使用本地缓存)

map/guava做的本地缓存,最主要的特点是 轻量以及快速,生命周期随着 jvm 的销毁而结束,并且在多实例的情况下,每个实例都需要各自保存一份缓存,缓存不具有一致性。
redis 或 memcached 之类的称为分布式缓存,在多实例的情况下,各实例共用一份缓存数据,缓存具有一致 性。缺点是需要保持 redis 或 memcached服务的高可用,整个程序架构上较为复杂。

redis 和 memcached 的区别

在这里插入图片描述
redis支持更丰富的数据类型,可以持久化

redis的key是字符串类型,value是string、list、set、hash、zset

hash的意思指的是映射,hash类型就是对象类型

key=JavaUser293847 
value={
    "id": 1,
    "name": "张三",
    "age": 22
}

set是无序不重复集合
zset是有序不重复集合

Redis过期key删除策略

redis key的过期时间,记录的时绝对时间,时间戳,比如4点设置10秒后过期,记录的过期时间戳是4点零10秒。记录的是这个时刻。

redis key有两种过期方式:主动式和被动式

  • 定期删除(主动式):redis默认是每隔 100ms 就随机抽取一些设置了过期时间的key,检查其是否过期,如果过期就删除。
    注意这里是随机抽取的。为什么要随机呢?你想一想假如 redis 存了几十万个 key ,每隔100ms就遍历所有的 设置过期时间的 key
    的话,就会给 CPU 带来很大的负载!

  • 惰性删除 (被动式):定期删除可能会导致很多过期 key 到了时间并没有被删除掉。所以就有了惰性删除。假如你的过期key,
    靠定期删除没有被删除掉,还停留在内存里,访问key的时候,会判断下key是否过期,如果过期就删除。
    注意:在redis主从集群中,master同步数据到slave,从节点不会主动删除key,必须等master的删除命令才会删除。确保主从节点的数据一致性

如果定期删除漏掉了很多过期 key,然后你也没及时去查,也就没走惰性删除,此时会怎么样?如果大量过期 key 堆积在内存里,导致 redis 内存块耗尽了,咋整?

这就要提到了Redis的内存淘汰机制。

内存淘汰机制
Redis的内存淘汰策略是指在Redis的用于缓存的内存不足时,怎么处理需要新写入且需要申请额外空间的数据,如何淘汰旧数据给新数据腾出内存空间。

redis 内存淘汰机制有以下几个:

  • noeviction:当内存不足以容纳新写入数据时,新写入操作会报错。
  • allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key。(这个是最常用的)
  • allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key。
  • volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key。
  • volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key。
  • volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除。

Redis的内存淘汰策略的选取并不会影响过期的key的处理。内存淘汰策略用于处理内存不足时的需要申请额外空间的数据;过期策略用于处理过期的缓存数据。
深入追问:
追问1: 简单介绍一下LRU淘汰机制吧
淘汰最近最少使用的;算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。
算法思路:

新数据插入到链表头部;

每当缓存命中(即缓存数据被访问),则将数据移到链表头部;

当链表满的时候,将链表尾部的数据丢弃。

redis面试详见https://baijiahao.baidu.com/s?id=1714823432163166272&wfr=spider&for=pc

redis事务

在这里插入图片描述

在这里插入图片描述

就是客户端执行完mutil之后,服务端会开始接受客户端的命令,只接收,不执行。然后服务端接收到exec命令之后,开始把接收到的一组命令一起执行,如果这一组命令有语法错误,则会直接报错,相当于java编译期就不通过,所以全都不会执行。但是如果没有语法错误,比如操作的是不存在的数据,这种语法没有错误,属于运行时报错。那么该条语句之前的命令则会执行成功。所以redis的事物是弱事物。无法保证全部回滚

redis锁可以保证原子性,但是无法保证一致性。

Redis 大key

在这里插入图片描述
在这里插入图片描述
1、指的是如果在分片存储的redis集群中,大key会被分到某个节点,导致该节点内存使用比较高,但是其他节点又没同样现象

bigkey的解决方案,能拆分就拆分。

redis bigkey 参考https://www.cnblogs.com/cangqinglang/p/17632287.html

redis如何解决key冲突

1、业务隔离,不同业务,使用不同redis
2、key设计,业务模块+系统名称+关键字+key的方式 等
3、节能是不同端操作共享变量,那就加分布式锁解决

如何提高缓存的命中率

1、提前加载到缓存

缓存穿透

缓存击穿:数据库和redis里面都没有的数据,如果并发访问这种数据,对数据库压力很大
1、缓存空对象到redis:开发维护简单,效果一般
2、使用布隆过滤器:开发维护麻烦,效果好

缓存击穿

数据库里面有数据,redis里面没有数据
解决方案:

  • 提前预热热点数据到redis
  • 代码方面 解决
    1、先查redis,发现没有数据
    2、加锁,查询redis,如果有数据则返回。如果没有数据进行下一步
    3、查询数据库,然后把数据缓存到redis
    双重检查锁。至于锁,可以用分布式锁,也可以用jdk的锁。使用jdk锁,可能会放一些请求打到数据库,请求量并不多,对数据库来说没影响的。

在这里插入图片描述
可以把代码提取出来封装到一个模板里面,只需要传入查询数据库的方法即可

缓存雪崩

大部分数据失效
解决方案:缓存的失效时间,不要设置同一时间,建议在时间后面添加随机数

Redis持久化

RDB方式持久化(默认)

在这里插入图片描述
RDB持久化策略
save 900 1 900秒内进行了一次update,就触发持久化
save 300 10 300秒内进行了10次update,就触发持久化
save 60 10000 60秒内进行了1w次update,就触发持久化

AOF持久化

将redis的写命令以日志追加的方式写入到持久化文件
在这里插入图片描述

在这里插入图片描述
AOf重写机制,比如上面自增命令执行了10次,aof会将命令修改为set lock 10。对持久化文件进行压缩。压缩后以rdb文件进行存储(redis4.0提供了混合持久化,指的就是这个)rdb是二进制方式存储,因此文件占用空间更小

aof重写机制的出发时机
在这里插入图片描述
64mb是默认配置,生产环境一般根据redis配置,会进行调大,比如调成几个g

RDB和ROF对比

在这里插入图片描述
在这里插入图片描述

Redis缓存一致性问题

https://baijiahao.baidu.com/s?id=1772845427366028025&wfr=spider&for=pc

Redis分布式锁

LRU和LFU的区别

https://blog.csdn.net/weixin_38937840/article/details/131551469

在这里插入图片描述

  • 21
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值