Redis面试专题
基础
Redis有哪些数据结构?
-
String(最常用)
是redis中最基本的数据类型,一个key对应一个value。
String类型是二进制安全的,意思是 redis 的 string 可以包含任何数据。如数字,字符串,jpg图片或者序列化的对象。
常用命令get 、 set 、 del 、 incr、 decr
等 -
List
链表(redis 使用双端链表实现的 List),是有序的,value可以重复,可以通过下标取出对应的value值,左右两边都能进行插入和删除数据。
常用命令lpush、rpush、lpop、rpop、lrange、llen、lindex
等 -
Hash
Map集合,key-map
! value是一个map集合
常用命令hset、hget、hlen、hsetnx
等 -
Set
无序集合 1.不允许有重复的元素,2.集合中的元素是无序的,不能通过索引下标获取元素,3.支持集合间的操作,可以取多个集合取交集、并集、差集
常用命令sadd、srem 、smembers 、sismember 、scard
等 -
Zset
有序集合--有序集合和集合有着必然的联系,保留了集合不能有重复成员
的特性,区别是,有序集合中的元素是可以排序的,它给每个元素设置一个分数,作为排序的依据。
另外
-
Geo
主要用于存储地理位置信息,并对存储的信息进行操作 例如:查看附近的人,计算与某点之间的距离等操作 -
HyperLogLog
用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定 的、并且是很小的。 -
Pub/Sub
发布订阅
Redis一个实例能存多少个key?
Redis一共有0-15
总共16
个db,默认使用db0
Redis一个数据库能存储2.5亿的Key,一个value的最大容量为512MB;
什么是Redis持久化?Redis有哪几种持久化方式?优缺点是什么?
持久化就是把内存的数据写到磁盘中去,防止服务宕机了内存数据丢失。
(Redis 数据都放在内存中,断电即失,所以持久化是必须的。将内存中的数据保存在磁盘,下一次启动的时候就可以恢复数据到内存中。)
Redis 提供了两种持久化方式:RDB(默认) 和AOF
-
RDB(Snapshotting)
:快照持久化、全量持久化
RDB持久化是指 在指定的时间间隔内将内存中的 数据集快照 写入磁盘,实际操作过程是主进程fork一个子进程,先将数据集写入临时文件(dump.rdb),写入成功后,再替换之前的文件,默认用二进制压缩存储。具体间隔多长时间持久化一次,要看配置文件具体配置。
默认配置为:
save 900 1 #在900秒(15分钟)之后,如果至少有1个key发生变化,Redis就会自动触发BGSAVE命令创建快照。
save 300 10 #在300秒(5分钟)之后,如果至少有10个key发生变化,Redis就会自动触发BGSAVE命令创建快照。
save 60 10000 #在60秒(1分钟)之后,如果至少有10000个key发生变化,Redis就会自动触发BGSAVE命令创建快照。
当然了,你也可以通过调用 SAVE (同步保存)或者 BGSAVE(异步保存),手动让 Redis 进行数据集保存操作。
一般来说,在生产环境很少执行 SAVE 操作,因为它会阻塞所有客户端,保存数据库的任务通常由 BGSAVE 命令异步地执行。
然而,如果负责保存数据的后台子进程不幸出现问题时, SAVE 可以作为保存数据的最后手段来使用。
-
AOF(append only file)
:增量持久化
AOF持久化 是以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,以文本的方式追加记录到
appendonly.aof
文件,可以打开文件看到详细的操作记录。
如果开启AOF后,默认持久化方式为每秒同步一次:
appendfsync everysec
每秒钟同步一次,显示地将多个写命令同步到硬盘
【注】如果两个都配了 则优先加载AOF。(同时开启两个持久化方案,则按照 AOF的持久化方案恢复数据。)
-
RDB优点
-
数据紧凑,利于备份
:RDB 是一个非常紧凑(compact)的文件,它保存了 Redis 在某个时间点上的数据集。这种文件非常适合用于进行备份:比如说,你可以在最近的 24 小时内,每小时备份一次 RDB 文件,并且在每个月的每一天,也备份一个 RDB 文件。这样的话,即使遇上问题,也可以随时将数据集还原到不同的版本。 -
性能最大化
:RDB对Redis的性能影响非常小,是因为在同步数据的时候他只是fork了一个子进程去做持久化的再由子进程完成这些持久化的工作,父进程无须执行任何磁盘 I/O 操作。
-
-
RDB缺点
-
容易造成数据丢失
:如果你想保证数据的高可用性,即最大限度的避免数据丢失,那么RDB将不是一个很好的选择。因为系统一旦在定时持久化之前出现宕机现象,此前没有来得及写入磁盘的数据都将丢失。 -
数据量大时消耗资源
:由于RDB是通过fork
子进程来协助完成数据持久化工作的,因此,如果当数据集较大时,客户端可能会暂停几毫秒甚至几秒;如果 你公司在做秒杀的时候他刚好在这个时候fork
了一个子进程去生成一个大快照,这就很容易出现问题。
-
-
AOF优点
-
保证数据的完整性
每一次修改都同步,文件的完整性会更好 - 每一秒都同步,可能会丢失一秒的数据
-
-
AOF缺点
- 对于相同数量的数据集来说,
AOF文件
通常要大于RDB文件
。AOF
在恢复大数据集时比RDB
的恢复速度要慢
。 - 根据同步策略的不同,AOF在运行效率上往往会慢于RDB。总之,每秒同步策略的效率是比较高的,同步禁用策略的效率和RDB一样高效。
- 对于相同数量的数据集来说,
二者选择的标准,就是看系统是愿意 牺牲一些性能,换取更高的缓存一致性(aof),还是愿意写操作频繁的时候,不启用备份来换取更高的性能,待手动运行save的时候,再做备份(rdb)。rdb这个就更有些 最终一致性(eventually consistent)的意思了。
进阶
Redis是单线程的为什么速度还这么快
Redis 读的速度是110000次/s,写的速度是80000次/s 。
1.redis是基于内存的,内存的读写速度非常快;
2.redis是单线程的,省去了很多上下文切换线程的时间;
3.redis使用多路复用技术,可以处理并发的连接;
简单解释下第二条:上下文切换就是cpu在多线程之间进行轮流执行(抢占cpu资源),而redis单线程的,因此避免了繁琐的多线程上下文切换
如果有大量的key需要设置同一时间过期,一般需要注意什么?
如果大量的key过期时间设置的过于集中,到过期的那个时间点,Redis可能会出现短暂的卡顿现象。严重的话会出现缓存雪崩。
我们一般需要在时间上加一个随机值,使得过期时间分散一些。(比如:添加随机1-10分钟的失效时间)
Redis如何实现延时队列?
Redis分布式锁
缓存穿透(缓存和数据库都没有对应的数据)及如何解决?
缓存穿透是指:用户想要查询一个数据,发现redis缓存数据库没有,也就是缓存没有命中,于是向持久层数据库查询。发现也没有,于是本次查询失败。当用户很多的时候,缓存都没有命中,于是都去请求了持久层数据库。
这会给持久层数据库造成很大的压力,这时候就相当于出现了缓存穿透。
- 方案一:缓存空对象
缓存空对象会有一个必须考虑的问题:
空值做了缓存,意味着缓存层中存了更多的键,需要更多的内存空间(如果是恶意攻击,缓存中的键值就会很多,问题更严重),比较有效的方法是针对这类数据设置一个较短的过期时间,让其自动过期。
- 方案二:布隆过滤器拦截
缓存击穿(所有查询全都聚集在缓存的某个点上)及如何解决?
缓存击,是指:一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库
,就像在一个屏障上凿开了一个洞。
缓存雪崩及如何解决?
缓存雪崩就是指:缓存由于某些原因(比如 宕机、cache服务挂掉 或 有大量的key在同一时间过期),导致大量请求涌入到数据库
,从而导致数据库崩溃,整个系统崩溃,发生灾难。
缓存雪崩、穿透和击穿,是缓存最大的问题,要么不出现,一旦出现就是致命性的问题!
哨兵模式
主从之间的数据怎么同步的?
你启动一台slave 的时候,他会发送一个psync命令给master ,如果是这个slave第一次连接到master,他会触发一个全量复制。master就会启动一个线程,生成RDB快照,还会把新的写请求都缓存在内存中,RDB文件生成后,master会将这个RDB发送给slave的,slave拿到之后做的第一件事情就是写进本地的磁盘,然后加载进内存,然后master会把内存里面缓存的那些新命名都发给slave。
参考文章: