文章目录
- 前言
- 1.第一问:redis支持哪些数据类型:
- 2 第二问:redis持久化方式和说明:
- 2.1 RDB(默认)持久化存储:
- 2.2 AOF:
- 2.3 持久化比较:
- 3.第三问:redis架构模式介绍:
- 4.第四问:redis常用命令和过期策略介绍:
- 5.第五问:redis分布式锁和队列:
- 6.第六问:redis针对缓存穿透、击穿、雪崩的解决方案:
- 总结
前言
java后端现在去外面面试,redis也是必须面试的问题点,因为在实际的开发当中,我们很多场景下秒杀、缓存、加锁会使用到redis。redis其实是数据库的一种,与传统的sqlserver和mysql的关系型数据库比较,属于非关系数据库,key-value形式存储。传统数据库遵循的是ACID规则。而redis遵循的是CAP理论。
1.第一问:redis支持哪些数据类型:
类型 | 命令 | 说明 |
String字符串 | set key value | String 是二进制安全的,也是基本数据类型,最大键值存储为512M,用于字符串缓存,加锁等场景 |
Hash类型 | hmset name key1 value1 key2 value2 | 是一个键值对的集合,非常适合存储字段比较多的对象 |
List类型 | 注意存储的是字符串列表,当然可以支持json字符串支持头部和尾部进行插入,同样支持头部和尾部读取,也支持索引获取元素,长度等方法 | 我之前用list做过队列,就是一个服务往里面写,另一个进行读取,进行了服务之间的解耦,当然这个数据量小的时候可以,数据量大的时候还是使用mq等中间件比较靠谱 |
Set集合 | sadd name value,set的是String 类型的无序集合 | 集合通过hash表实现,添加、删除、查找的复杂度都是O(1) |
zset类型 | 有序集合, zadd name score value,跟set一样,是String类型元素集合,不允许重复成员,因为元素都会关联一个分数,所以通过分数的排序使其具有排序的特性,成员唯一,但是分数可以重复 | 使用与需要排序的集合的使用场景 |
2 第二问:redis持久化方式和说明:
持久化的目的是防止服务宕机内存中的数据丢失。
2.1 RDB(默认)持久化存储:
RDB快照存储,隔一段时间fork一个子进程进行快照形式的保存数据,缺点是容易丢失数据。RDB是Redis DataBase缩写,rdbsSave和rdbLoad两个函数进行和磁盘文件交互。
2.2 AOF:
追加模式,aof是Append-only file缩写,就是定期往磁盘文件进行追加持久化的内容,缺点是导致后面的追加文件很大,但是优点是不容易丢失数据。
2.3 持久化比较:
- aof的更新频率比rdb高,优先使用aof进行数据还原
- aof比rdb安全,但是文件会更大
- rdb的性能比aof好
- 如果配置的两种持久化策略,优先使用的aof
这里提一下redis客户端和服务端的通讯协议是:RESP。
特点是:
实现简答、快速解析、可读性好
3.第三问:redis架构模式介绍:
单机版: 一个服务提供给多个客户端使用:
特点是:简单
缺点:内容存储有限、处理能力有限、无法高可用
主从复制:
一个master 多个slave,主服务器发生在自己身上的数据更新给从服务器,来保证主从相同。
特点:降低了度压力
缺点:无法保证高可用,主挂了就挂了,也没有解决写的压力
哨兵:
Redis sentinel 是一个分布式系统中监控redis主从服务器,在主服务器下线时自动进行故障迁移。
监控:监控主从服务器之间是否正常
提醒:当监控的redis服务器出现问题,会向管理员和其他应用发出通知
自动故障迁移:当主服务器不能正常工作时,开始自动故障迁移。
特点:
保证高可用、监控各个节点、自动故障迁移
缺点:主从模式,切换时间可能都是数据,缺点是没有解决master写的压力
集群(proxy 型)用的不多:
Twemproxy 是一个 Twitter 开源的一个 redis 和 memcache 快速/轻量级代理服务器; Twemproxy 是一个快速的单线程代理程序,支持 Memcached ASCII 协议和 redis 协议。
特点:1、多种 hash 算法:MD5、CRC16、CRC32、CRC32a、hsieh、murmur、Jenkins
2、支持失败节点自动删除
3、后端 Sharding 分片逻辑对业务透明,业务方的读写方式和操作单个 Redis 一致
缺点:增加了新的 proxy,需要维护其高可用。
集群(直连型):
redis 3.0之后支持redis-cluster集群,Redis-Cluster采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他所有节点连接。
特点:
1、无中心架构(不存在哪个节点影响性能瓶颈),少了 proxy 层。
2、数据按照 slot 存储分布在多个节点,节点间数据共享,可动态调整数据分布。
3、可扩展性,可线性扩展到 1000 个节点,节点可动态添加或删除。
4、高可用性,部分节点不可用时,集群仍可用。通过增加 Slave 做备份数据副本
5、实现故障自动 failover,节点之间通过 gossip 协议交换状态信息,用投票机制完成 Slave到 Master 的角色提升。
缺点:
1、资源隔离性较差,容易出现相互影响的情况。
2、因为数据通过异步复制,不保证数据的强一致性
补充:目前来说最好的一个架构
4.第四问:redis常用命令和过期策略介绍:
命令 | 说明 |
Keys pattern/keys aa* keys * | 查看key相关 |
Exists key | 查询key是否存在存在返回1不存在返回0 |
set | set key value进行存储键值对 |
setnx | 设置key对应的值为String类型的value,如果key已经存在,返回0,nx是not exist的意思 |
del key | 删除key |
Incr | 对key进行加1的操作并且返回新的值 |
incrby | 指定Key加的值并且返回最新值 |
Decr | 在原来的值的基础上减1并返回结果 |
Decrby | 指定减的值 |
Rename | 重命名 |
Type | 返回数据类型 |
这里要说明的是如果使用的是SpringBoot,RedisTemplate 里面直接点点操作会有对应的api操作。
这里还要说的是如果你面试的能够回答出来,SpringBoot1x中使用的是jedis连接池 ,SpringBoot2x中使用的是lettuce 连接池,性能有很大提升,会是加分项。
Redis过期策略:
我们知道设置过期时间命令:
expire key time
字符串独有的过期设置:
setx(String key ,int seconds,String value)
除了字符串其他的类型都是依靠expire设置过期时间。如果不设置过期时间就是永不过期。
三种过期策略:
策略 | 说明 | 优点 | 缺点 |
定时删除 | 在设置key的时候设置一个定时器为key,当到期时删除key | 保证尽快释放内存 | key多cpu占用多,影响性能 |
惰性删除 | key过期的时候不删除,获取的时候检查key是否过期,若过期则删除,返回null | 占用cpu少 | 大量key过期不删除,内存泄露会发生 |
定期删除 | 每隔一段时间删除过期key的操作 | 能有效降低cpu的占用和惰性删除的缺点 | 内存不如定时删除,cpu不如惰性删除 |
redis采用的惰性删除和定期删除的组合策略。
RDB和AOF对过期key都会有个判断的操作,所以过期key对持久化无影响。
5.第五问:redis分布式锁和队列:
redis的分布式锁之前setnx,先加锁再加过期时间,但是新版本中增加了原子锁:commands.set(Constant.前缀+ “:” + key, “1”, “NX”, “EX”, expireSecond);NX/EX实现分布式原子锁,防止两死锁的发生。
异步队列:就像我上面提到的就是使用list类型实现,lpush进行生产消息,lpop进行消费消息。当然这种队列只适合简单的队列场景,涉及到过期队列并发高等还是应该使用mq。
6.第六问:redis针对缓存穿透、击穿、雪崩的解决方案:
名词 | 说明 | 解决 |
穿透 | 存在则缓存返回,不存在则查询db,恶意查询不存在的key对后端压力增大就叫穿透 | 查询为空的时候缓存下,查询以后更新缓存,过滤key |
击穿 | 缓存中没有数据库中有,穿透是数据库中也可能没有 | 设置热点key永不过期,加互斥锁,保证第一个访问去数据库查询数据,其他的都是走缓存空 |
雪崩 | 缓存服务器重启或者大量缓存失效,都去访问数据库,引起压力过大 | key的过期时间分布均匀 ,避免短时间大量key过期,加锁避免并发并发量大访问控制流量 |
总结
上面总的来说把redis整个的面试涉及到的点进行了一个总结。