zoukankan      html  css  js  c++  java
  • Redis面试题

    Redis

    1.Redis 是什么?特点,适用场景及应用场景?

    Redis是一个基于内存存储数据运行并支持持久化、使用key/value形式存储的高性能的nosql数据库

    特点:

    1.支持数据持久化   :可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。

    2.支持多种数据结构   :不仅支持简单的key-value类型数据,同时还提供list、set、zset、hash等数据结构的存储

    3.支持数据备份        :master-salve模式的数据备份

    适合用于存储频繁访问,数据量较小的场景下

    计算器,缓存,分布式锁,token令牌,短信验证码,订单有效期

    redis线程是安全的

    2.Redis线程是否安全、效率为什么这么高?

    redis是单线程的,线程是安全的,redis采用多路io复用,基于内存操作,单线程没有上下文切换所以效率高

    3.Redis 和Memcache区别是什么?

    1.redis支持多种数据类型

    2.可以持久化数据

    3.虽然都是基于内存存储,但是redis比Memcache快

    4.Redis事务你是如何理解的?

    通过redis事务的三特性,了解到redis事务是一个单独的隔离操作,知道事务中所有命令都会按照顺序执行不会被其它命令插队干扰;没有隔离级别的概念(队列中的命令没有提交前都不会实际被执行);不保证原子性说明事务中如果有一条运行错误其它正确命令也会执行(命令编译错误,其它的命令都不执行)没有回滚;ps:事务与事务之间是队列保证原子性,同一个队列(事务)中命令和命令之间是不能保证原子性的。

    既然支持事务,和mysql事务的区别及为什么不支持回滚?

    redis不支持行锁不支持事务回滚只支持事务的取消                     

    redis只有程序发出错误才停止,其他错误都是正常运行 所以不支持

    5.Redis事务具有隔离性么?

    redis是单线程方式执行事务的,总是以串行的方式运行,所有事务具有隔离性

    6.Redis事务的命令?

    使用multi开启组队然后输入需要执行的命令(组队时语法写错会解散组队),输入exec开始执行,discard解散组队;在执行multi之前watch可以监控一个或多个key,如果在事务执行前key被改动那么事务会被打断;unwatch取消监视

    语法错误时,使用命令不存在或命令参数不对时正确的命令也不会执行,运行错误,在命令执行时出现的错误,比如使用散列类型操作集合类型的key,这种错误在redis实际执行无法发现的,在事务中会被接受并执行。

    7.Redis持久化谈谈你的理解  (高可用)

    redis持久化有二种方式,一种是RDB一种是AOF。

    我先来谈谈RDB吧, RDB是默认的持久化机制,在指定时间间隔内将内存的数据以快照的形式保存到硬盘中,生成一个dump.rdb文件;将这个文件拷贝到工作目录下,备份数据会直接加载

    优点:适合大规模数据恢复;容灾性好,可以将文件拷贝到多个安全的硬盘;性能优化强,子进程负责持久化,主进程继续处理命令

    缺点:数据安全性低,持久化期间redis意外宕机会丢失数据;数据集大时会影响性能,比如做秒杀,突然fork一个子进程去备份,客户端会暂停几秒

    原理:  fork:赋值一个与当前进程一样的进程,一个全新的进程作为子进程来持久化  备份时,主进程会单独fork一个子进程来进行持久化,主进程就不需要做其他Io操作

    在来谈谈AOF,AOF是以日志的形式来记录每次写操作,当redis重启的时候会根据日志文件将写指令重新执行一次完成数据恢复,默认是不开启的想使用的时候需要开启;当文件越来越大可以重写节约磁盘空间

    优点:备份稳健,数据不易丢失;可读的日志文件,可以处理误操作;通过配置appendfsync everysec 每秒钟同步一次,可能会丢失1s内的数据,但是效率非常高。appendfsync always 可以执行一次写操作就会保存到日志文件中;

    缺点:占用磁盘空间较大;恢复速度慢;每次读写同步,有性能压力;存在个别bug,恢复失败

    总结来说同时开启Redis优先使用AOF,AOF比RDB安全但RDB性能比AOF好;要使用的话,二种都一起使用,单独用RDB会丢失很多数据,单独用AOF数据恢复没RDB快,建议第一时间用RDB恢复库AOF来做数据不全

    宕机的情况下,RDB会丢失最近一次持久化数据,AOF会丢失一次写操作

    全量同步与增量同步的区别

    全量同步:就是每天定时(避开高峰期)或者采用一个周期实现将数据拷贝到一个地方也就是Rdb存储。

    增量同步:比如采用对行为的操作实现对数据的同步,也就是AOF。

    全量与增量的比较:增量同步比全量同步更加消耗服务器的内存,但是能够更加的保证数据的同步。

    8.Redis和Mysql的双读双写数据一致性解决问题

    双写:

    方式1:直接清除Redis的缓存,重新读取数据库即可

    方式2:使用mq异步订阅mysql binlog实现增量同步

    方式3:使用alibaba的canal框架

    mysql和redis实现数据同步不可能强制一致性,可以出现短暂数据不一致,但是最后都是采用最终一致性方案

    双读:

    读的时候,先读缓存,缓存没有的话,就读数据库,然后取出数据后放入缓存,同时返回响应。

    9.Redis内存防止撑爆有哪些方法

    1.通过配置文件maxmemory参数设置内存大小

    2.使用内存淘汰策略

    3.使用集群

    10.Redis内存淘汰策略

    Redis的内存淘汰策略是指在Redis的用于缓存的内存不足时,怎么处理需要新写入且需要申请额外空间的数据。

    全局的键空间选择性移除

    noeviction:当内存使用达到阈值的时候,执行命令直接报错    默认

    allkeys-lru:在所有的key中,优先移除最近未使用的key。(推荐)

    allkeys-random:在所有的key中,随机移除某个key。

    设置过期时间的键空间选择性移除

    volatile-lru:在设置了过期时间的键空间中,优先移除最近未使用的key。

    volatile-random:在设置了过期时间的键空间中,随机移除某个key。

    volatile-ttl:在设置了过期时间的键空间中,具有更早过期时间的key优先移除。

    11.Redis中过期键的删除策略

    定时过期:每个设置过期时间的key都需要创建一个定时器,到过期时间就会立即清除。该策略可以立即清除过期的数据,对内存很友好;但是会占用大量的CPU资源去处理过期的数据,从而影响缓存的响应时间和吞吐量。

    惰性过期:只有当访问一个key时,才会判断该key是否已过期,过期则清除。该策略可以最大化地节省CPU资源,却对内存非常不友好。极端情况可能出现大量的过期key没有再次被访问,从而不会被清除,占用大量内存。

    定期过期:每隔一定的时间,会扫描一定数量的数据库的expires字典中一定数量的key,并清除其中已过期的key。该策略是前两者的一个折中方案。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果。

    Redis key的过期时间和永久有效分别怎么设置?

    EXPIRE和PERSIST命令。

    我们知道通过expire来设置key 的过期时间,那么对过期的数据怎么处理呢?

    定时去清理过期的缓存;

    当有用户请求过来时,再判断这个请求所用到的缓存是否过期,过期的话就去底层系统得到新数据并更新缓存。

    两者各有优劣,第一种的缺点是维护大量缓存的key是比较麻烦的,第二种的缺点就是每次用户请求过来都要判断缓存失效,逻辑相对比较复杂!具体用哪种方案,大家可以根据自己的应用场景来权衡。

    12.Redis中的分布锁

    如何解决 Redis 的并发竞争 Key 问题:使用分布锁锁 zookeeper和redis都可以 然后讲实现

    理解:

    本地锁:在多个线程中,保证只有一个线程执行(线程安全问题)

    分布锁:在分布式中,保证只有一个jvm执行(多个jvm线程安全问题)

    核心思路:

    1.获取锁:多个不同的jvm同时创建一个相同的标记(全局唯一的)只要谁能够创建成功,谁就获取锁

    2.释放锁:释放该全局唯一的标记,其他的jvm重新进入到获取资源

    3.超时锁(没有获取锁,已经获取锁):等待获取锁的超时时间,已经获取到锁,设置锁的有效期

    应用场景:当服务器做集群,保证定时任务具有幂等性;缓存击穿

    实现:

    使用setnx命令来获取锁,用expire给锁加一个过期时间防止锁忘记释放

    引发出问题  如果在setnx之后执行expire之前进程意外crash或者要重启维护了,那会怎么样?

    锁得不到释放会变成死锁,set指令有个非常复杂的参数,这个应该是可以同时把setnx和expire合成一条指令来用的解决这个问题。

    什么是 RedLock

    Redis 官方站提出了一种权威的基于 Redis 实现分布式锁的方式名叫 Redlock,此种方式比原先的单节点的方法更安全。它可以保证以下特性:

    安全特性:互斥访问,即永远只有一个 client 能拿到锁

    避免死锁:最终 client 都可能拿到锁,不会出现死锁的情况,即使原本锁住某资源的 client crash 了或者出现了网络分区

    容错性:只要大部分 Redis 节点存活就可以正常提供服务

    集群  高可用

    集群无法选择库默认0号库;主从是异步复制;Redis并不能保证数据的强一致性,这意味这在实际中集群在特定的条件下可能会丢失写操作。

    13.Redis 主从复制

    使用的背景(也可以当做问题):

    主从复制有什么作用?

    具有高可用性:服务器出现故障或者宕机的情况下,可以切换到从服务器上,让从服务器充当主服务器,保证服务的正常运行。

    数据的备份:主从复制将主库上的数据复制到了从库上,相当于是一种热备份机制,也就是在主库正常运行下进行备份,不会影响到服务;

    读写分离:通过主从复制的方式来同步数据,然后通过读写分离提升数据库的并发处理能力

    单个redis如果因为某种原因宕机的话,可能会导致整个redis服务不可用你怎么解决?

    这时候使用Redis的主从复制,实现一主多从,主节点负责写,从结点负责读数据,实现读写分离;所有读请求走读结点可以支撑读的高并发!

    那数据一致性的问题?

    主节点会将数据采用全量或者增量的形式同步给结点保证数据的一致性;首次使用全量方式(二进制执行dump文件,RDB),往后使用增量的形式(每次主结点写操作时,请求aof日志文件)

    节点过多的话会导致对主节点同步多个从节点压力非常大,效率非常慢应该怎么解决?

    建议使用多主多从或树状形式的方式保证同步效率

    过程或原理(主从之间怎么同步的?):

    当slave向master建立socket连接,会发送一个psync命令给主节点 ,如果是这个slave第一次连接到master,他会触发一个全量复制。master就会启动一个线程,生成RDB快照,还会把新的写请求都缓存在内存中,RDB文件生成后,master会将这个RDB发送给slave的,slave拿到之后做的第一件事情就是写进本地的磁盘,然后加载进内存,以后master每当写操作会通过aof日志文件发送给slave保证数据一致。   

    我觉得这个原理也可以回答一致性问题

    主从复制产生网络延迟怎么办:Redis中数据同步是不可能保证强一致性的,只能最终一致性,因此只能手动补偿

    当redis主节点出现问题上述内容全部gg 引出哨兵

    使用:在redis.conf文件#replicaof <masterip> <masterport>下配置ip和端口号 slaveof 192.168.212.160 6379  有密码情况下masterauth <密码>       使用info replication查看

    14.Redis 哨兵

     哨兵机制: 顾名思义就是看哨的;当主节点出现问题时候可以用哨兵机制解决,保证redis的高可用,实现自动化故障发现与故障转移

     使用流程:

     每个节点配置 sentinel.conf文件,sentinel monitor mymaster 主节点IP 端口号 从节点数量     启动哨兵 redis-sentinel sentinel.conf

     哨兵提供的功能:

     集群监控:负责监控 redis master 和 slave 进程是否正常工作。

     消息通知:如果某个 redis 实例有故障,那么哨兵负责发送消息作为报警通知给管理员。

     故障转移:如果 master node 挂掉了,会自动转移到 slave node 上。

     配置中心:如果故障转移发生了,通知 client 客户端新的 master 地址。

     原理或提供功能:

     监控:哨兵机制每隔10s时间只需要配置监听我们的主节点就可以获取当前整个Redis集群的环境列表是否正常工作,采用info 命令形式。

     哨兵不建议是单机的,最好每个Redis节点都需要配置哨兵监听。

     哨兵集群原理是如何:多个哨兵都执行同一个主的master节点,订阅到相同都通道,有新的哨兵加入都会向通道中发送自己服务的信息,该通道的订阅者可以发现新哨兵的加入,随后相互建立长连接。

     故障转移+配置中心:单个哨兵会向主的master节点发送ping的命令,如果master节点没有及时的响应,哨兵会认为该master节点为“主观不可用状态”会发送给其他都哨兵确认该Master节点是否不可用,当前确认的哨兵节点数>=quorum(可配置),会实现重新选举主节点,并在配置文件中更新 新的master地址。

     注意点:哨兵必须用三个实例去保证自己的健壮性的,哨兵+主从并不能保证数据不丢失,但是可以保证集群的高可用。

    15.Redis Cluster集群  分区

    Redis哨兵集群模式,每个节点都保存全量同步数据,冗余的数据比较多;而在Redis Cluster模式中集群中采用分片集群模式,可以减少冗余数据

    Redis3.0开始官方推出了集群模式 RedisCluster,原理采用hash槽的概念,预先分配16384个卡槽(类似于分库分表),并且将该卡槽分配给具体服务的节点;通过key进行crc16(key)%16384 获取余数,余数就是对应的卡槽的位置,一个卡槽可以存放多个不同的key,每份数据分片会存储在多个互为主从的多节点上,数据写入先写主节点,再同步到从节点(支持配置为阻塞同步),同一分片多个节点间的数据不保持一致性,读取数据时,当客户端操作的key没有分配在该节点上时,redis会返回转向指令,指向正确的节点,扩容时时需要需要把旧节点的数据迁移一部分到新节点,从而将读或者写转发到该卡槽的服务的节点,当主节点宕机时自动选举。

    最大的优点:无中心架构支持动态扩容、缩容;具有哨兵的监控和自动转移功能;连接集群任何一个节点即可使用

    缺点:运维复杂,数据迁移需要人工;只能使用0号库;

    16.Redis 缓存异常

    缓存穿透

    产生的背景:

    缓存穿透是指使用不存在的key进行大量的高并发查询,导致查询不到数据,每次请求都要都要穿透到数据库查询,使数据库压力非常大,导致数据库崩掉;

    解决方案:

    接口层实现api限流、用户授权、id检查等

    从缓存和数据库都取不到数据的话,设置一个key并将数据库空值放入缓存中做value,设置30s有效期避免使用同一个id对数据库攻击压力大;

    使用布隆过滤器

    缓存击穿

    产生背景:

    在高并发的情况下,当一个缓存key(热点key)过期时,因为访问该key请求较大,多个请求同时发现缓存过期,因此对多个请求同时数据库查询、同时向Redis写入缓存数据,这样会导致数据库的压力非常大;

    解决方案:

    使用分布式锁,使用本地锁           (互斥锁)

    设置热点数据永不过期或者异步延长过期时间;

    保证在分布式情况下,使用分布式锁保证对于每个key同时只允许只有一个线程查询到后端服务,其他没有获取到锁的权限,只需要等待即可;这种高并发压力直接转移到分布式锁上,对分布式锁的压力非常大。

    使用本地锁与分布式锁机制一样,只不过分布式锁适应于服务集群、本地锁仅限于单个服务使用。

    缓存雪崩

    缓存雪崩指缓存服务器重启或者大量的缓存集中在某个时间段失效,突然给数据库产生了巨大的压力,甚至击垮数据库的情况。

    解决思路:对不用的数据使用不同的失效时间,加上随机数;有更新操作更新缓存

    区别:

    穿透:当查询一个key 不存在的情况

    雪崩:多个key同时失效情况

    击穿:单个key(热点key)失效的情况下

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

    布隆过滤器

    场景:

    某些存储系统的设计中,会存在空查询缺陷:当查询一个不存在的key时,需要访问慢设备,导致效率低下。缓存穿透

    优点是不需要存储key,节省空间

    缺点:算法判断key在集合中时,有一定的概率key其实不在集合中,无法删除

    理解:

    布隆过滤器适用于判断一个元素是否在集合中,实现原理采用二进制向量数组和随机映射函数;二进制数组为1时对应一个映射函数,每次使用时都需要先缓存预热,其中也存在一个冲突问题,

    布隆过滤器会根据key计算hash值,可能与已存放的元素hash产生冲突都为1,因为可能会产生误判。

    可以通过将二进制数组长度设置大些,减少误判率。

    其他

    Jedis与Redisson对比有什么优缺点?

    Jedis是Redis的Java实现的客户端,其API提供了比较全面的Redis命令的支持;Redisson实现了分布式和可扩展的Java数据结构,和Jedis相比,功能较为简单,不支持字符串操作,不支持排序、事务、管道、分区等Redis特性。Redisson的宗旨是促进使用者对Redis的关注分离,从而让使用者能够将精力更集中地放在处理业务逻辑上。

    假如Redis里面有1亿个key,其中有10w个key是以某个固定的已知的前缀开头的,如果将它们全部找出来?

    使用keys指令可以扫出指定模式的key列表。

    对方接着追问:如果这个redis正在给线上的业务提供服务,那使用keys指令会有什么问题?

    这个时候你要回答redis关键的一个特性:redis的单线程的。keys指令会导致线程阻塞一段时间,线上服务会停顿,直到指令执行完毕,服务才能恢复。这个时候可以使用scan指令,scan指令可以无阻塞的提取出指定模式的key列表,但是会有一定的重复概率,在客户端做一次去重就可以了,但是整体所花费的时间会比直接用keys指令长。

    使用Redis做过异步队列吗,是如何实现的

    使用list类型保存数据信息,rpush生产消息,lpop消费消息,当lpop没有消息时,可以sleep一段时间,然后再检查有没有信息,如果不想sleep的话,可以使用blpop, 在没有信息的时候,会一直阻塞,直到信息的到来。redis可以通过pub/sub主题订阅模式实现一个生产者,多个消费者,当然也存在一定的缺点,当消费者下线时,生产的消息会丢失。

    Redis如何实现延时队列

    使用sortedset,使用时间戳做score, 消息内容作为key,调用zadd来生产消息,消费者使用zrangbyscore获取n秒之前的数据做轮询处理。

    回收就是内存满了 淘汰

     

  • 相关阅读:
    Neko's loop HDU-6444(网络赛1007)
    Parameters
    SETLOCAL
    RD / RMDIR Command
    devenv 命令用法
    Cannot determine the location of the VS Common Tools folder.
    'DEVENV' is not recognized as an internal or external command,
    How to change Visual Studio default environment setting
    error signing assembly unknown error
    What is the Xcopy Command?:
  • 原文地址:https://www.cnblogs.com/kmcl1314/p/14416682.html
Copyright © 2011-2022 走看看