Redis面试题锦

本文总结了Redis面试的常见问题,包括Redis的基本概念、与Memcached的区别、应用场景、数据结构及其使用、持久化策略、并发竞争问题的解决、回收机制、大量数据插入方法以及分区与持久化方式的选择。同时探讨了Redis的性能问题及其解决方案,提供了优化建议,旨在帮助读者深入理解Redis的特性和实战技巧。
摘要由CSDN通过智能技术生成

Redis面试题锦

概述

常见问题

一、概述

最近领导让我来面试一些候选人,我挑了一些高频知识点总结,以免到时候忽悠不了候选人(哈哈),此为Redis篇。

二、常见问题

2.1 Redis概念(参考百度百科)

1. Redis全称:REmote DIctionary Server(Redis) ,即远程字典服务,是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
2. 支持的数据类型:String: 字符串、Hash: 散列、List: 列表、Set: 集合、Sorted Set: 有序集合
3. 操作类型:push/pop、add/remove及交集并集等等,且全是原子操作。
4. Redis为了效率,也同memcached一样,将数据缓存在内存中,但是会定期将数据写入磁盘或者将修改追加到日志文件,请再次基础上实现master-slave同步。
5. Redis支持主从同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。这使得Redis可执行单层树复制。存盘可以有意无意的对数据进行写操作。由于完全实现了发布/订阅机制,使得从数据库在任何地方同步树时,可订阅一个频道并接收主服务器完整的消息发布记录。同步对读取操作的可扩展性和数据冗余很有帮助。

2.2 比较Redis与Memcached

1. redis除了支持k-v,还支持其他的数据结构;Memcached只支持k-v和String
2. redis支持主从复制功能(数据备份)
3. Redis支持持久化操作,可以在断电重启后,再次加载数据进行使用;Memcached将数据全部存储在内存之中,断电后消失。
4. Memcached是多线程、非阻塞IO复用模型。;Redis是单线程的IO复用模型。
  • 若想更进一步了解,《脚踏两只船的困惑 - Memcached与Redis》 请点击
  • 复用:多个任务,一个线程

2.3 如何选择Memcached和redis

使用Redis的String类型做的事,都可以用Memcached替换,以此换取更好的性能提升; 除此以外,优先考虑Redis

2.4 使用Redis的好处

1. 速度:数据存储于内存之中,类似于hashMap,查找和操作的时间复杂度为O(1);
2. 支持多种数据类型
3. 支持主从复制,持久化,可用作消息队列,缓存(设置key过期时间)
4. 支持事务:如果在入队时出错,则都不会执行;在非入队时出错,那么成功执行

2.5 Redis常见数据结构使用场景

命令用法:
COMMAND KEY_NAME
2.5.1 String
127.0.0.1:6379> set my_redis redis  //设置k-v
OK
127.0.0.1:6379> get my_redis //获取value
"redis"
127.0.0.1:6379> GETRANGE my_redis 0 3 //获取子集
"redi"
127.0.0.1:6379> GETSET my_redis mongodb //返回value并重置
"redis"
127.0.0.1:6379> get my_redis
"mongodb"
127.0.0.1:6379> SETEX my_redis 10 redis //设置过期时间
OK
127.0.0.1:6379> get my_redis
"redis"
127.0.0.1:6379> get my_redis //已过期
(nil)
127.0.0.1:6379> SETEX my_redis 5 redis1 //设置过期时间
OK
127.0.0.1:6379> get my_redis 
"redis1"
127.0.0.1:6379> SETNX my_redis redis //SET if Not eXists
(integer) 1
127.0.0.1:6379> get my_redis 
"redis"
127.0.0.1:6379> STRLEN my_redis //返回value长度
(integer) 5
127.0.0.1:6379> DEL my_redis
(integer) 1
127.0.0.1:6379> get my_redis 
(nil)
  • 其他对多个key及value中数字的加减操作未展示
  • 常用命令: set,get,decr,incr,mget 等。
2.5.2 Hash
127.0.0.1:6379> HMSET date y "2020" m "09" d "30" //设置hash
OK
127.0.0.1:6379> hgetall date //查看hash
1) "y"
2) "2020"
3) "m"
4) "09"
5) "d"
6) "30"
127.0.0.1:6379> HDEL date y //删除hash中的field
(integer) 1
127.0.0.1:6379> hgetall date
1) "m"
2) "09"
3) "d"
4) "30"
127.0.0.1:6379> HEXISTS date d //检查hash中包含某个field
(integer) 1
127.0.0.1:6379> HSETNX date t 16
(integer) 1
127.0.0.1:6379> hgetall date
1) "m"
2) "09"
3) "d"
4) "30"
5) "t"
6) "16"
  • 常用命令: hget,hset,hgetall 等。

2.5.3 List操作

127.0.0.1:6379> LPUSH my_arr redis
(integer) 1
127.0.0.1:6379> LPOP my_arr
"redis"
  • 常用命令: lpush,rpush,lpop,rpop,lrange等

2.5.4 Set

127.0.0.1:6379> SADD myset redis
(integer) 1
127.0.0.1:6379> SADD myset mysql
(integer) 1
127.0.0.1:6379> SADD myset mysql
(integer) 0
127.0.0.1:6379> SADD myset mongodb
(integer) 1
127.0.0.1:6379> SMEMBERS myset
1) "mongodb"
2) "redis"
3) "mysql"
4) "mqsql"
  • 常用命令: sadd,spop,smembers,sunion 等

2.5.5 sorted set

127.0.0.1:6379> ZADD myst 1 redis
(integer) 1
127.0.0.1:6379> ZADD myst 2 mysql
(integer) 1
127.0.0.1:6379> ZADD myst 3 mongodb
(integer) 1
127.0.0.1:6379> ZRANGE myst 0 10 WITHSCORES
1) "redis"
2) "1"
3) "mysql"
4) "2"
5) "mongodb"
6) "3"
  • 常用命令: zadd,zrange,zrem,zcard等

2.6 如何保证redis中都是热点数据

相关:redis内存数据集达到一定大小后会施行淘汰策略
    1. volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
    1. volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
    1. volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
    1. allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
    1. allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
    1. no-enviction(驱逐):禁止驱逐数据

2.7 Redis的并发竞争问题如何解决?

背景:redis使用单线程模式,采用队列模式将并发访问变为串行访问。Redis本身没有锁的概念,多个客户端连接时并不存在竞争,但在客户端对redis访问时会发生连接超时、数据转换错误、阻塞、客户端关闭连接等问题,这些问题均由客户端连接混乱导致。

解决方法如下

    1. 客户端角度:为保证每个客户端间正常有序与Redis进行通信,对连接进行池化,同时对客户端读写Redis操作采用内部锁同步。
    1. 服务器角度,利用setnx实现锁。

对于第一种,需要应用程序自己处理资源的同步,可以使用的方法比较通俗,可以使用锁机制;第二种需要用到Redis的setnx命令,但是需要注意一些问题。

2.8 Redis回收机制

    1. 引用计数法:
    1. LRU算法:最近最久未使用算法

2.9 Redis 大量数据插入

背景:使用正常模式的Redis,会不停地进行IO操作,思路是将多条数据,使用管道一次插入。
    1. 以前使用netcat方式,创建redis命令集文件data.txt, 执行命令:(cat data.txt; sleep 10) | nc localhost 6379 > /dev/null,但无检查错误能力。
    1. pipe mode:cat data.txt | redis-cli --pipe,
      使用redis-cli将有效的确保错误输出到Redis实例的标准输出里面

2.10 Redis 分区的优势、不足以及分区类型

分区:分区是分割数据到多个Redis实例的处理过程,因此每个实例只保存key的一个子集。

优势与劣势

  • 优势:

集合了计算资源,使用了更多地cpu、网络、内存来提高redis的性能

  • 劣势:

多个分区的数据不能像同一分区那样使用并集、交集、事务等操作

分区类型

  • 范围分区:维护区间范围到实例的映射表(额外开销,不推荐)
  • 哈希分区:使用hash算法,来选择实例

2.11 Redis持久化方式及选择

持久化方式

  • RDB:间隔时间内对数据进行快照存储
  • AOF:记录每次对服务器的写操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,Redis协议追加保存每次写的操作到文件末尾.Redis还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大。

如何选择

  • RDB:默认开启,会按照配置的指定时间将内存中的数据快照到磁盘中,创建一个dump.rdb文件,Redis启动时再恢复到内存中。Redis会单独创建fork()一个子进程,将当前父进程的数据库数据复制到子进程的内存中,然后由子进程写入到临时文件中,持久化的过程结束了,再用这个临时文件替换上次的快照文件,然后子进程退出,内存释放。需要注意的是,每次快照持久化都会将主进程的数据库数据复制一遍,导致内存开销加倍,若此时内存不足,则会阻塞服务器运行,直到复制结束释放内存;都会将内存数据完整写入磁盘一次,所以如果数据量大的话,而且写操作频繁,必然会引起大量的磁盘I/O操作,严重影响性能,并且最后一次持久化后的数据可能会丢失;
  • AOF:以日志的形式记录每个写操作(读操作不记录),只需追加文件但不可以改写文件,Redis启动时会根据日志从头到尾全部执行一遍以完成数据的恢复工作。包括flushDB也会执行。主要有两种方式触发:有写操作就写、每秒定时写(也会丢数据)。因为AOF采用追加的方式,所以文件会越来越大,针对这个问题,新增了重写机制,就是当日志文件大到一定程度的时候,会fork出一条新进程来遍历进程内存中的数据,每条记录对应一条set语句,写到临时文件中,然后再替换到旧的日志文件(类似rdb的操作方式)。默认触发是当aof文件大小是上次重写后大小的一倍且文件大于64M时触发。
    当两种方式同时开启时,数据恢复Redis会优先选择AOF恢复。一般情况下,只要使用默认开启的RDB即可,因为相对于AOF,RDB便于进行数据库备份,并且恢复数据集的速度也要快很多。开启持久化缓存机制,对性能会有一定的影响,特别是当设置的内存满了的时候,更是下降到几百reqs/s。所以如果只是用来做缓存的话,可以关掉持久化。

2.12 Redis常见性能问题和解决方案?

    1. Master最好不要做任何持久化工作,如RDB内存快照和AOF日志文件
    1. 如果数据比较重要,某个Slave开启AOF备份数据,策略设置为每秒同步一次
    1. 为了主从复制的速度和连接的稳定性,Master和Slave最好在同一个局域网内
    1. 尽量避免在压力很大的主库上增加从库
    1. 主从复制不要用图状结构,用单向链表结构更为稳定,即:Master <- Slave1 <- Slave2 <- Slave3…
      这样的结构方便解决单点故障问题,实现Slave对Master的替换。如果Master挂了,可以立刻启用Slave1做Master,其他不变。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值