你真的对Redis很清楚吗?来看看这些面试题

1.什么是Redis,有何优点作用,为什么效率高?

redis是nosql中的一种,把数据存储在内存中的数据库,优点:高性能,读写速度快,支持多种字符,支持事务,和丰富的特性

纯内存数据库,非阻塞io,单线程模型,减少上下文切换。使用hash结构。

2.Redis相比memcached有哪些优势?

redis支持多种数据结构,memcached只能用普通的字符窜

redis读写速度比他快,

redis支持事务,支持持久化

 

3.Redis是单线程还是多线程?为什么选择单线程?为什么执行速度快?  Redis 6出现了多线程来处理网络处理方面

他用单线程处理数据快,用多线程考虑上下文的切换和线程锁会影响性能。

执行速度快是因为他是纯内存操作,异步非阻塞I/O

Redis4.0就开始有多线程的概念了,一般都是通过多线程的方式在后台删除对象,以及redis模块实现阻塞命令。

在redis6把网络处理部分做成多线程处理方式,get/set操作性能会提供很多

 

4.Redis支持哪几种数据类型?

List按照插入顺序排序。,粉丝列表或者消息队列功能。

String 以kv行式进行存储,一般用于常规的kv缓存应用。或复制的计数功能的缓存

set 哈希表实现,元素不重复,做全局去重的功能

hash是一个k  v是键值对集合,一般适用于存储对象,存储用户信息等,单点登录

zset 和set一样也是string类型元素的集合, 数据插入集合时,已经进行天然排序  应用于排行榜

 

5.为什么Redis需要吧所有数据放到内存中?

因为redis读取速度快,如果放在磁盘会影响读取性能

 

6.Redis集群方案应该怎么做?都有哪些方案?

redis cluster  自带的集群,集群中任意节点平等,每个节点保持连接活跃,任意节点可用获取其他节点的数据。

redis集群主要搭建了6台,3主(为了保证redis的投票机制)3从(高可用),每个主服务器都有一个从服务器,作为备份机。

Redis集群的时候没有使用一致性的hash,而是引入了哈希槽的概念,一般Redis集群的时候有16384个哈希槽,每个key值通过CRC16.效验后来决定发置那个槽,每个节点负责一部分hash槽。16384也就是最大节点数。

Redis Cluster主从模式

redis cluster 为了保证数据的高可用性,加入了主从模式,一个主节点对应一个或多个从节点,主节点提供数据存取,从节点则是从主节点拉取数据备份,当这个主节点挂掉后,就会有这个从节点选取一个来充当主节点,从而保证集群不会挂掉。

 

redis集群,搭建几台,怎么搭建

3台(为了保证redis的投票机制)每个主服务器都有一个从服务器。,Redis集群方式有很多种,我们采用的是redis-cluster集群,这种发送采用的是无中心结构,每个节点保持数据的整个集群的状态,每个节点都和其他所有节点连接。在redis集群中,我们会用哨兵模式去监控redis的状态。防止发生master宕机。一般这种几率很少出现。

 

8.如何保证Redis的数据都是热点数据?

可以设置redis的allkeys-lru内存回收策略,每次访问或插入数据的时候,清理最近使用最少的数据。

 

9.Redis有哪些适用的场景?

会话缓存 订阅发布,排行排,消息队列,全页缓存

 

10.Redis哈希槽的概念

redis集群的时候没有使用一致性的hash,而是引入哈希槽的概念,一般redis集群的时候有16384个哈希槽,每key值通过crc16校验后来决定放在哪个节点

 

11. redis的持久化方式

rdb:指定时间间隔内,将内存中的数据快照的方式保存到文件中。优点:对文件数据恢复数据效快,缺点:可能会丢失数据,不能保证数据的高可用。

 

aof:根据配置把每次写操作的命令写入到aof文件中,当redis重启,通过文件来恢复数据。优点:数据安全性高。缺点:恢复速度慢,效率低,因为文件比较大。

使用redis-port工具来将rdb文件恢复数据。 Aof看有没有flushall命令有就删除,然后重启redis。就会通过aof文件来恢复数据。

 

12.redis挂掉了怎么办?怎么实现高可用?

保存数据的话,做持久化,然后搭建redis集群,主机宕机,可以使用备用。

 

13.你怎么定期清理redis中缓存?设置过期时间需要注意什么?

主键失效和淘汰策略.
  在Redis当中,有生存期的key被称为volatile。在创建缓存时,要为给定的key设置生存期,当key过期的时候(生存期为0),它可能会被删除。

在使用DEL、SET、GETSET等会覆盖key对应value的命令操作一个设置了过期时间的key的时候,会导致对应的key的过期时间被清除。Incr/lpush/hset等命令则不会清除过期时间

 

14.使用redis分布式锁吗?怎么实现?

基于redisson里面的Rlock锁来实现。或者使用事务。

 

15.redis的同步机制了解么?

主从同步,第一次同步时,主节点做一次bgsave,记录到内存中,然后将rdb文件同步到复制节点,然后将rdb加载到内存,主节点将修改的操作同步到复制节点中,就完成了同步过程。 修改的时候会做记录,然后加载到内存中,然后同步到其他节点上。

 

16.redis集群有哪些?redis集群是怎么实现的?

Redis Sentinal(哨兵模式)着眼于高可用,在master宕机时会自动将slave提升为master,继续提供服务。

cluster模式为了解决单机Redis容量有限的问题,将Redis的数据根据一定的规则分配到多台机器。

 

17.redis的缓存竞争并发问题怎么解决?

做秒杀的时候产生的问题。使用分布式锁,抢到锁就做set操作,不推荐使用redis的事务机制。因为我们的生产环境,基本都是redis集群环境,做了数据分片操作。你一个事务中有涉及到多个key操作的时候,这多个key不一定都存储在同一个redis-server上

 

18.Redis过期策略和内存淘汰机制是什么?

过期策略分三种:定时删除:设置key的过期时间同时创建定时器,让定时器在key的过期时间到了时,立即执行删除操作

惰性过期:放任过期不管,用户获取key检测是否过期,过期就删除,没有就返回。

定期过期:每隔一定的时间,会扫描一定数量的数据库的expires字典中一定数量的key,并清除其中已过期的key。

因为redis是采用定期删除+惰性删除就是定期删除会导致某一些key过期了没有被删除,因为他是随机检查的,惰性删除是用户获取key的时候检查删除key,如果用户设置key的过期时间,1没有被定时删除检查到,2用户没有去获取这个key,那么就会大量过期key堆积在内存里,导致redis内存块耗尽了,这个时候就需要redis的内存淘汰策略了。

内存淘汰策略分6种: 通过 config set maxmemory-policy volatile-lru   设置

noeviction: 默认的策略,即当内存使用达到阈值的时候,所有引起申请内存的命令都会报错;
allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰 。

allkeys-random:随机移除某个key

volatile-random:从已设置过期时间的数据中任意选择数据淘汰。

volatile-lru:从已设置过期时间的数据中挑选最近最少使用的数据淘汰。

volatile-ttl:从已设置过期时间的数据中挑选将要过期的数据淘汰;适合场景:这种策略使我们可以向Redis

 

19.redis事务

1.事务是一个单独的隔离操作,事务在执行的过程中,不会被其他的命令打断,要么全部操作成功,要么全都失败。开启事务:multi 用queued添加数据不会添加成功,而是记录下来,事务提交exec把前面添加的数据提交,如果中间没有其他人做操作就可以成功,不然就添加失败,放弃事务:discard

 

20.redis的wathc机制

就是一个乐观锁,就是监视一个或多个key,如果在事务执行之前,key值被修改过,则事务被打断。

 

21.redis如何设置密码?

设置密码:config set requirepass ****   授权密码:auth  *****

 

22.如何保证mysql和redis数据的一致性?

1.一般正常的话是先删除缓存再保存数据到db中。采用延迟双删除策略,先删除缓存,再写数据库,休眠500毫秒,再删除缓存。设置缓存时间等。(查询,先读缓存有就取出数据,没有就读数据库 ,更新,删除 先删除缓存在做操作。)

缺点:如果没有删除缓存的情况下可能存储着数据不一致的问题。

2.mq异步更新缓存(基于定义binlog的同步机制)MySQL中产生了新的写入、更新、删除等操作在binlog里面进行记录,订阅读取binlog后分析,利用消息队列,就可以把binlog相关的消息推送至Redis,Redis再根据binlog中的记录,对Redis进行更新。消息队列可以采用阿里的canal(肯那儿)+kafka或者rabbitmq来实现(模仿的mysql主从复制

 

23. redis的安全机制

1.修改配置文件,使用禁止一些命令,和禁止远程修改db文件地址。

2.降低权限运行redis服务。可以配置禁止登陆。

3.要么为redis配置密码验证,或者防止外网访问redis

 

24.redis高并发粒度问题

粗粒度锁:

这时候,普遍的做法是加锁,但是如果对整个访问redis的动作加锁,那么等于多个线程串行访问了!

细粒度加锁:

我们这里的做法是对key进行细粒度加锁,每个key拥有一把锁,只对key进行并发控制,key与key之间允许并发。

数据颗粒度一般指影响的数据范围大小

 

25.单线程的redis如何利用多核cpu机器?

在同一台机来器上启动Redis的多个实例,将其当作不同的服务器

 

26.缓存穿透,缓存击穿,缓存雪崩是什么?解决方案?

1.缓存穿透:利用不存在的key来查询数据库,因为缓存中没有该key就去查询数据库,去数据库查询key的时候不管查询到了没有都进行缓存,如果是null就返回null值,。定期清楚为null的数据。

2.缓存击穿:经常热点访问的一个key,有10W并发量,同你这个key没有做缓存的时候去查询db(缓存时间到期的期间),使用互斥锁来实现,第一个人拿到锁了,后面的人就只能等待(或者休眠2S),然后重新返回这个方法查询。

3.缓存雪崩:缓存雪崩是指在我们设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到DB,DB瞬时压力过重雪崩。原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。

 

27.redis读写分离和数据分片

要在集群的情况下一步主服务器尽量的少读少写,其他的服务可以配置多少的读写次数。(数据分片)Key的hash槽为多少去访问那个服务器。

数据分片:指的是在Redis集群中为每一台服务器逻辑分配一定数量的槽位,然后按照一定的算法,计算数据存放的槽位,从而达到将数据均匀分散在几台服务器中,达到负载均衡的效果。

 

28.Redis在什么情况下会导致整个集群不可用?

如果有3个节点的集群,如果没有复制模型的情况下,某一个节点失败了,就会导致整个集群不可用

 

29.Redis主从复制?高可用哨兵?

有台服务器在主服务器配置中配置主从关系,主服务器写入数据会同步到从服务器中。

监控多个redis服务运行情况,服务器出现问题,则将从服务器提升成主服务器。

 

30.集群中如何复制?测试redis的连通性? 管道有何用?

1.异步复制  2.ping   3. 利用管道,客户端可以一次性发送多个请求而不用等待服务器的响应,待所有命令都发送完后再一次性读取服务的响应,降低请求时间从而提升性能

 

31.redis如何做内存优化?

1.缩减键值的长度(LZO压缩字符串)(能用简单的就用简单的)(进redis之前还可以压缩内容)

2.共享对象池(尽量使用整数对象)redis启动的时候默认会生成一个0-9999的整数对象共享池。

3.配置内存回收策略,设置最近少使用的进行清理。

4.编码优化(在配置中:config set hash-max-ziplist-entries 65。这样value大于65字节才转换成hash table。)

5.设置内存上限 6.控制key的数量,尽量使用hash。因为string的内存占用比较大key比较分散,hash支持hashtable和ziplist比string节约5倍的空间,但是hash不好设置单独某个值的过期时间

 

32.redis-cluster集群工作原理,及数据如何存放以及算法?

1.自动将数据分片,每个master上放一部分数据 2.提供内置的高可用支持,部分master不可用时,还可继续工作

Redis中

集群中分片的算法有、

Hash算法:key,首先计算 hash 值,然后对节点数取模。然后存在不同的 master 节点上。缺点:当某个master节点宕机,大量的数据就需要重新计算写入缓存和如果存在大量的请求,几乎大部分请求都获取不到缓存,那么直接请求数据库,就可能导致数据库挂了,因为这个节点上的master挂了,数据需要重新计算和写入

一致性Hash算法:将hash空间组织成一个虚拟的圆环,按顺时针方向来存储数,将各个master节点进行hash来确定每个节点在hash环上的位置。来了一个key,计算hash值来确定数据落在hash环上的位置,然后顺时针旋转找到离自己最近的节点进行存储。

问题1:如果节点太少时,可能造成节点发布不均匀,造成缓存热点的问题。一致性 hash 算法引入了虚拟节点机制,即对每一个节点计算多个 hash,每个计算结果位置都放置一个虚拟节点。这样就实现了数据的均匀分布,负载均衡。

在一致性哈希算法中,如果一个节点挂了,受影响的数据仅仅是此节点到环空间前一个节点(沿着逆时针方向行走遇到的第一个节点)之间的数据,其它不受影响。增加一个节点也同理。

 

Redis-cluster的hash slot(哈希槽)算法: Redis-cluster集群的时候有16384个哈希槽,每个key值通过CRC16.效验后来决定发置那个槽,每个master节点负责一部分hash槽。哈希槽让节点的增加和移除很简单,增加master节点,就将其他master的hash slot移动部分过去,减少一个master,就将它的hash slot移动到其他master上去

Redis开发规范

1.可读性和可管理性

以业务名 (或数据库名) 为前缀(防止 key 冲突),用冒号分隔,比如业务名: 表名: id
ugc:video:1

2.简洁性

保证语义的前提下,控制 key 的长度,当 key 较多时,内存占用也不容忽视,例如:
user:{uid}:friends:messages:{mid}简化为u:{uid}:fr:m:{mid}。

3.不要包含特殊字符

反例:包含空格、换行、单双引号以及其他转义字符


4.拒绝 bigkey

防止网卡流量、慢查询,string 类型控制在 10KB 以内,hash、list、set、zset 元素个数不要超过 5000。


5.选择适合的数据类型

例如:实体类型 (要合理控制和使用数据结构内存编码优化配置, 例如 ziplist,但也要注意节省内存和性能之间的平衡)
反例:
set user:1:name tom
set user:1:age 19
set user:1:favor football
正例:
hmset user:1 name tom age 19 favor football

6.控制 key 的生命周期

redis 不是垃圾桶,建议使用 expire 设置过期时间

Redis排查命令

ping  测试redis的连通性。

object idletime [key]  查看某个key的空闲时间。

object encoding [key]:返回指定key的内部存储使用的编码格式

object FREQ [key]:返回指定key访问频率的对数,当淘汰策略为LFU时,这一命令会被用到

Info Memory  查看redis内存使用情况

slowlog 查看查询慢的命令有哪些,默认命令耗时超过10毫秒就会记录到查询日志队列中。
slowlog get 2 查询2个

查看redis服务器资源监控RedisLive

检查服务端tcp连接:netstat -nat|grep -i "6379"|wc -l

检查服务端连接是否达到最大值:查看服务端支持的最大连接:CONFIG GET maxclients

查看当前服务端建立的 连接:connected_clients


如果是向磁盘保存数据失败为:Can’t save in background: fork: Cannot allocate memory
修改liunx内核参数 vm.overcommit_memory=1

overcommit_memory有三种取值:0, 1, 2

0::检查是否有足够的可用内存供进程使用;有则允许申请,否则,内存申请失败,并把错误返回给应用进程;

1:表示内核允许分配所有的物理内存,而不管当前的内存状态如何;

2:表示内核允许分配超过所有物理内存和交换空间总和的内存。

猜你喜欢

转载自blog.csdn.net/qq_41085151/article/details/107859689