Redis面试题

1. NoSQL是什么,出现的目的和意义是什么?

NoSQL(Not Only SQL),指的是非关系型的数据库。NoSQL用于超大规模数据的存储。

NoSQL,泛指非关系型的数据库。随着互联网web2.0网站的兴起,传统的关系数据库在处理web2.0网站,特别是超大规模和高并发的SNS类型的web2.0纯动态网站已经显得力不从心,出现了很多难以克服的问题,而非关系型的数据库则由于其本身的特点得到了非常迅速的发展。
NoSQL数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战,尤其是大数据应用难题。 研究NoSQL 数据库,非常适合许多现代应用程序,例如移动、Web 和游戏等应用程序,它们需要灵活、可扩展、高性能和功能强大的数据库以提供卓越的用户体验。

因此,我们总结NoSQL数据库在以下的这几种情况下比较适用:

  • 数据模型比较简单;

  • 需要灵活性更强的IT系统;

  • 对数据库性能要求较高;

  • 不需要高度的数据一致性;

  • 对于给定key,比较容易映射复杂值的环境

2. Redis的优点和缺点?

  • Redis 优势

    优势:性能极高,数据是存储在内存中;丰富的数据类型,支持多种数据类型操作;所有操作都是原子性的;支持通知, key过期等特性;使用自己实现的分离器,代码量很短,读写效率非常高;支持持久化。

    • 性能极高 – 由于数据是存储在内存中(Redis能读的速度是110000次/s,写的速度是81000次/s )。

    • 丰富的数据类型 – Redis支持的类型 String, Hash,List, Set 及 Ordered Set 等数据类型操作。

    • 原子性 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。

    • 丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。

    • 高速读写 redis使用自己实现的分离器,代码量很短,没有使用lock(MySQL),因此效率非常高。

    • 持久化 Redis直接将数据存储到内存中,要将数据保存到磁盘上,Redis可以使用两种方式实现持久化过程。定时快照(snapshot):每隔一段时间将整个数据库写到磁盘上,每次均是写全部数据,代价非常高。第二种方式基于语句追加(aof):只追踪变化的数据,但是追加的log可能过大,同时所有的操作均重新执行一遍,回复速度慢。

  • Redis 缺点

    • 耗内存,占用内存过高。

    • 在线扩容,Redis难以支持在线扩容,尤其在集群场景里,当存储容量达到上限后,在线扩容会非常困难。

3. Redis有哪些应用场景

缓存 排行榜 计数器 分布式会话 分布式锁 社交网络 最新列表 消息系统

  • 缓存
    缓存现在几乎是所有中大型网站都在用的必杀技,合理的利用缓存不仅能够提升网站访问速度,还能大大降低数据库的压力。Redis提供了键过期功能,也提供了灵活的键淘汰策略,所以,现在Redis用在缓存的场合非常多。

  • 排行榜
    很多网站都有排行榜应用的,如京东的月度销量榜单、商品按时间的上新排行榜等。Redis提供的有序集合数据类构能实现各种复杂的排行榜应用。

  • 计数器
    什么是计数器,如电商网站商品的浏览量、视频网站视频的播放数等。为了保证数据实时效,每次浏览都得给+1,并发量高时如果每次都请求数据库操作无疑是种挑战和压力。Redis提供的incr命令来实现计数器功能,内存操作,性能非常好,非常适用于这些计数场景。

  • 分布式会话
    集群模式下,在应用不多的情况下一般使用容器自带的session复制功能就能满足,当应用增多相对复杂的系统中,一般都会搭建以Redis等内存数据库为中心的session服务,session不再由容器管理,而是由session服务及内存数据库管理。

  • 分布式锁
    在很多互联网公司中都使用了分布式技术,分布式技术带来的技术挑战是对同一个资源的并发访问,如全局ID、减库存、秒杀等场景,并发量不大的场景可以使用数据库的悲观锁、乐观锁来实现,但在并发量高的场合中,利用数据库锁来控制资源的并发访问是不太理想的,大大影响了数据库的性能。可以利用Redis的setnx功能来编写分布式的锁,如果设置返回1说明获取锁成功,否则获取锁失败,实际应用中要考虑的细节要更多。

  • 社交网络
    点赞、踩、关注/被关注、共同好友等是社交网站的基本功能,社交网站的访问量通常来说比较大,而且传统的关系数据库类型不适合存储这种类型的数据,Redis提供的哈希、集合等数据结构能很方便的的实现这些功能。

  • 最新列表
    Redis列表结构,LPUSH可以在列表头部插入一个内容ID作为关键字,LTRIM可用来限制列表的数量,这样列表永远为N个ID,无需查询最新的列表,直接根据ID去到对应的内容页即可。

  • 消息系统
    消息队列是大型网站必用中间件,如ActiveMQ、RabbitMQ、Kafka等流行的消息队列中间件,主要用于业务解耦、流量削峰及异步处理实时性低的业务。Redis提供了发布/订阅及阻塞队列功能,能实现一个简单的消息队列系统。另外,这个不能和专业的消息中间件相比。

4.Redis默认在什么情况下会进行持久化操作?RDB和AOF区别?

持久化就是把内存的数据写到磁盘中去,防止服务宕机了内存数据丢失。

Redis持久化存储支持两种方式:RDB和AOF。RDB一定时间取存储文件,AOF默认每秒去存储历史命令, Redis是支持持久化的内存数据库,也就是说redis需要经常将内存中的数据同步到硬盘来保证持久化。

RDB:是redis的默认持久化机制。
快照是默认的持久化方式。这种方式是就是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为 dump.rdb。
1、服务器正常关闭时  ./bin/redis-cli shutdown
2、key满足一定条件,会进行快照

AOF:aof 比快照方式有更好的持久化性  aof的方式也同时带来了另一个问题,持久化文件会变的越来越大。
RDB是redis的默认持久化机制,在指定的时间间隔内,执行了指定次数的写操作,则会将内存中的数据写入到磁盘中。即在指定目录下生成一个dump.rdb文件。Redis重启会通过加载dump.rdb文件恢复数据。
AOF默认是不开启的。它的出现是为了弥补RDB的数据的不一致性,所以它采用日志的形式来记录每个写操作,并追加到文件中。Redis 重启后会根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。

5. Redis内存维护策略?

为数据设置超时时间   采用LRU算法动态将不用的数据删除

采用LRU算法动态将不用的数据删除

内存管理的一种页面置换算法,对于在内存中但又不用的数据块(内存块)叫做LRU,操作系统会根据哪些数据属于LRU而将其移出内存而腾出空间来加载另外的数据。

volatile-lru:设定超时时间的数据中,删除最不常使用的数据.

allkeys-lru:查询所有的key中最近最不常使用的数据进行删除,这是应用最广泛的策略.

volatile-random:在已经设定了超时的数据中随机删除.

allkeys-random:查询所有的key,之后随机删除.

volatile-ttl:查询全部设定超时时间的数据,之后排序,将马上将要过期的数据进行删除操作.

noeviction(默认):如果设置为该属性,则不会进行删除操作,如果内存溢出则报错返回.

volatile-lfu:从所有配置了过期时间的键中驱逐使用频率最少的键

allkeys-lfu:从所有键中驱逐使用频率最少的键

6. 描述String类型常用命令和应用场景

赋值语法: setnx key1 value
取值语法: getrange key start end
删值语法:DEL KEY_Name
strlen key :返回 key 所储存的字符串值的长度
自增:INCR KEY_Name
自减:DECR KEY_NAME
字符串拼接:APPEND  KEY_NAME VALUE 命令用于为指定的 key 追加至未尾,如果不存在,为其赋值

**应用场景**
- String通常用于保存单个字符串或JSON字符串数据
- 因String是二进制安全的,所以你完全可以把一个图片文件的内容作为字符串来存储
- 计数器(常规key-value缓存应用。常规计数: 微博数, 粉丝数)
- 手机验证功能  限制登入功能  防止重复提交

7. 描述Hash类型常用命令和应用场景

赋值语法:
HSET KEY  FIELD VALUE
取值语法:
HGET KEY FIELD : 获取存储在HASH中的值,根据FIELD得到VALUE
hmget KEY field[field1]: 获取key所有给定字段的值 
hgetall KEY: 返回HASH表中所有的字段和值 
删值语法:
hdel KEY field1[field2]: 删除一个或多个HASH表字段 
其它语法:
hsetnx key field value : 只有在字段 field 不存在时,设置哈希表字段的值
hincrby key field increment : 为哈希表 key 中的指定字段的整数值加上增量 increment 。
hincrbyfloat key field increment: 为哈希表 key 中的指定字段的浮点数值加上增量 increment 。
hexists key field: 查看哈希表 key 中,指定的字段是否存在

应用场景:
(存储一个用户信息对象数据)

8. 描述List类型常用命令和应用场景

赋值语法:LPUSH/RPUSH key value1 [value2]  将一个或多个值插入到列表头部(从左侧添加/从右侧添加)
       LPUSHX/RPUSHX key value   :将一个值插入到已存在的列表头部/尾部。如果列表不在,操作无效
取值语法: 
    llen key      :获取列表长度
    lindex key index   :通过索引获取列表中的元素
    lrange key start stop  :获取列表指定范围内的元素
删值语法:LPOP/RPOP key  移出并获取列表的第一个元素(从左侧删除/从右侧删除)
​
ltrim key start stop :让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。
​
修改语法:
   lset key index value  :通过索引设置列表元素的值
   linsert key before|after world value :在列表的元素前或者后插入元素 描述:将值 value 插入到列表 key 当中,位于值 world 之前或之后。
​
高级语法:
rpoplpush a1  a2   :a1的最后元素移到a2的左侧
brpoplpush a1  a2 timeout  :从列表中弹出一个值,将弹出的元素插入到另外一个列表中并返回它; 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
​
​
项目常应用于:1、对数据量大的集合数据删减 2、任务队列   实例:热点新闻列表   用户系统登录注册短信实名认证等 订单系统的下单流程等  

9. 描述Set类型常用命令和应用场景

赋值语法: 
  SADD key member1 [member2] :向集合添加一个或多个成员 
​
取值语法: 
  scard key :获取集合的成员数 
  smembers key  :返回集合中的所有成员 
  sismembers key member  :判断 member 元素是否是集合 key 的成员(开发中:验证是否存在判断) 
  srandmember key [count] :返回集合中一个或多个随机数     
 
删除语法:  
  srem key member1 [member2] :移除集合中一个或多个成员
  spop key [count]  :移除并返回集合中的一个随机元素
  smove source destination member :将 member 元素从 source 集合移动到 destination 集合
​
差集语法: 
  SDIFF key1  [key2]   :返回给定所有集合的差集(左侧)
  sdiffstore destination key1 [key2]  :返回给定所有集合的差集并存储在 destination 中
交集语法: 
  sinter key1 [key2]  :返回给定所有集合的交集(共有数据) 
  sinterstore destination key1 [key2]  :返回给定所有集合的交集并存储在 destination 中
并集语法: 
  sunion key1 [key2] :返回所有给定集合的并集 
  sunionstore destination key1 [key2]  :所有给定集合的并集存储在 destination 集合中
  
  
  **常应用于:对两个集合间的数据[计算]进行交集、并集、差集运算** 
1、利用集合操作,可以取不同兴趣圈子的交集,以非常方便的实现如共同关注、共同喜好、二度好友等功能。  对上面的所有集合操作,你还可以使用不同的命令选择将结果返回给客户端还是存储到一个新的集合中。
2、利用唯一性,可以统计访问网站的所有独立 IP、存取当天[或某天]的活跃用户列表。
​
判断用户名/手机号/邮箱 是否存在    
数据统计(抽奖等) 
结果集运算(有两组数据,求两组数据的 交集、差集、并集)

10. 描述Zset类型常用命令和应用场景

赋值语法: 
  zadd key score1 member1 [score2 member2]  :向有序集合添加一个或多个成员,或者更新已存在成员的分数  
​
取值语法: 
  zcard key  :获取有序集合的成员数
  ZCOUNT key min max :计算在有序集合中指定区间分数的成员数
   zrank key member :返回有序集合中指定成员的索引
  zranke key start stop [WITHSCORES] :通过索引区间返回有序集合成指定区间内的成员(低到高)
  zrangebyscore key min max [WITHSCORES] [LIMIT] :通过分数返回有序集合指定区间内的成员
  zrevrange key start stop [WITHSCORES] :返回有序集中指定区间内的成员,通过索引,分数从高到底
  zrevarangebyscore key max min [WITHSCORES] :返回有序集中指定分数区间内的成员,分数从高到低排序
删除语法: 
  DEL key   :移除集合 
  ZREM key member [member ...] :移除有序集合中的一个或多个成员
  zremrangebyrank key start stop :移除有序集合中给定的排名区间的所有成员(第一名是0)(低到高排序)
  zremrangebyscore key min max :移除有序集合中给定的分数区间的所有成员
  
zincrby key increment member    :增加memeber元素的分数increment,返回值是更改后的分数
  
  
  
  **常应用于:排行榜 销量排名,积分排名等**   
  
  积分、成绩、等等排行榜   需求1:在zset中插入10名同学成绩
                        需求2:按成绩由高到低,查出前3名同学成绩信息
                        需求3:查询成绩在60- 80分之间 的同学成绩信息
                        
                        奥运金牌排行榜
                        
                        快递从发货到拿到的流程

11. 什么是缓存穿透、解决方案?为什么会发生穿透?如何避免?

缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,造成缓存穿透。

解决方法:

  1. 设定一个特定值,如果有获取到这个值,则报错返回

  2. 在外层做一个大的list集合,先将获取的数据和这个集合进行比较,若不存在则直接拦截掉

为什么出现穿透?
答:因为用户恶意攻击(修改网站请求地址信息或URL参数) 解决? 答:通过加密算法改id值,不让客户端看到关键信息

12. 什么是缓存雪崩、解决方案?为什么会发生雪崩?如何避免?

雪崩:缓存大量失效的时候,引发大量查询数据库。

解决办法:

用锁/分布式锁或者队列串行访问
缓存失效时间均匀分布

1 加锁排队. 限流-- 限流算法.

2 数据预热

比如微博热搜,app首页数据已经电商秒杀活动商品等等.....

解决:一般的做法是对缓存数据的缓存有效时间做控制;我们尽量避免让缓存数据同一时间失效;我们设置统一的缓存时间后,再加上一个随机缓存时间;

假设并发有10000个请求,想达到第一次请求从数据库中获取,其他9999个请求从redis中获取这种效果

避免:使用互斥锁排队

双重检测锁压测

13. 什么是Redis集群、Redis集群特点(Cluster)

Redis Cluster集群是实际使用最多的模式。

为了在大流量访问下提供稳定的业务,集群化是存储的必然形态 未来的发展趋势肯定是云计算和大数据的紧密结合 只有分布式架构能满足要求

1、所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽。
2、节点的fail是通过集群中超过半数的节点检测失效时才生效。
3、客户端与redis节点直连,不需要中间proxy层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。
4、redis-cluster把所有的物理节点映射到[0-16383]slot上(不一定是平均分配),cluster 负责维护。
5、Redis集群预分好16384个哈希槽,当需要在 Redis 集群中放置一个 key-value 时, redis 先对key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。

14. 什么情况下集群单个master不可用?什么情况下整个集群不可用?

投票机制。投票过程是集群中所有master参与,如果半数以上master节点与master节点通信超时(cluster-node-timeout),认为当前master节点挂掉。
​
如果集群任意master挂掉,且当前master没有slave.集群进入fail状态,也可以理解成集群的slot映射[0-16383]不完整时进入fail状态. 如果集群超过半数以上master挂掉,无论是否有slave,集群进入fail状态。

15. 数据库和redis缓存一致性?

  • 实时同步

  • 异步队列

16、key的生存时间到了,Redis会立即删除吗?

不会立即删除。
定期删除:
惰性删除:

17、缓存数据倾斜、降级、预热?

数据倾斜分为以下两种:数据量倾斜,数据访问倾斜。
缓存倾斜也叫热点key倾斜,解决办法:热点key复制出多个子key,每个子key的value值一样,查询的时候使用hash取模算法,将压力分摊到不同的服务端节点。

缓存降级/服务降级:
当访问量剧增、服务出现问题时,仍然需要保证核心的服务还是可用的,这时可以采用关闭一些非核心的服务的方式,来保证核心服务可用。即,丢卒保帅。
降级的最终目的是保证核心服务可用。

缓存预热
缓存预热就是系统上线之后,将一些缓存数据先加载到缓存系统中。这样就可以避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题。
用户直接查询事先被预热好的缓存数据!

posted @ 2023-01-17 22:41  Rix里克斯  阅读(78)  评论(0)    收藏  举报