Redis面试重点-2
13. 如果避免雪崩?
- 原因:高并发下,大量可以同时失效,造成的并发访问数据库。
- 解决:
- 在原有过期时间上设置随机过期时间。
- 通过加锁或者队列来控制查询数据库线程的数量。
14. Redis扛不住了,万级流量打到DB上怎么处理?
- 往穿透、击穿、雪崩上聊。
15. Redis中的事务三条指令是什么?当事务中某条指令到达或执行失败了,怎么处理。
特点:
事务支持一次执行多个命令,一个事务中所有命令都会被序列化。在事务执行过程,会按照顺序串行化执行队列中的命令,其他客户端提交的命令请求不会插入到事务执行命令序列中。
命令:**(@&@)
- Multi命令:用于标记一个事务块的开始。
- Exec命令:用于执行所有事务块内的命令。
- Watch命令:用于监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。
WATCH key [key ...]
事务执行阶段:
- 事务开始(MULTI)
- 命令入队
- 事务执行(EXEC)
TIPS:
- 失败就是失败,即不能保证事务的原子性、并且不支持回滚。
- 少使用事务,事务中命令尽量少。
16. 如何进行缓存预热?
- 提前把数据塞入Redis中,你知道那些是热点数据,几乎是不知道,会造成线上很多数据没有命中。
- 开发逻辑上要避免差集,即没有缓存的数据,可能会出现穿透、击穿、雪崩的问题。
- 解决方案对缓存查询加锁,KEY不存在,就加锁,然后查DB写入缓存,然后解锁;其他进程如果发现有锁就等待,等解锁后再从缓存查询数据。
17. 数据库与缓存数据不一致如何去解决?
总:
读操作时,不会导致数据不一致。写操作时,缓存和数据库都需要修改,可能造成数据不一致。此时主要需要考虑两个问题:
- 执行顺序的问题:先更新缓存,还是先更新数据库
- 更新缓存的策略问题:缓存内容变化时,是选择修改缓存(update),还是直接淘汰缓存(delete)
读操作:先从缓存,再DB;插入操作:只插入DB、不缓存;更新操作:先淘汰缓存,再更新DB。
更新缓存的策略问题:
建议直接淘汰缓存。简单更新值的操作,淘汰与更新操作消耗差不多;复杂数据更新,可能更新比淘汰更复杂。
执行顺序的问题:
- 方案一:先淘汰缓存,再更新数据库(建议)
- 第一步淘汰缓存成功,第二步更新数据库失败,此时再次查询缓存,最多会有一次cache miss。
- 方案二:先更新数据库,再淘汰缓存
- 第一步更新数据库成功,第二部淘汰缓存失败,出现数据不一致,需要再引入“重试机制”
Tips:
- Redis是缓存,更倾向于有时差。
- 尽量减少DB的操作。
- 落地还是使用canal【渴闹】。
18. Redis主从模式:
主从模式的作用:
主从模式主要是为解决单机故障问题,将数据冗余出一份或多份(一主一从或多从),当主遇到故障时,进行主从切换,提高可用性。此外,主从节点还可以采用读写分离的方式,降低主节点的运行负载。
主从如何同步:
- 全量同步:新增一个从节点时,进行全量同步。执行replicaof命令后开始。
- 命令传播:主从节点完成全量同步后,会维护一个长连接,用来同步后续主节点的数据操作,即命令传播(基于长链接)。
- 增量同步:遇到网络问题或从节点重启,主节点上没有同步到从节点的数据,会进行一次增量同步。
- 原理:主节点有一个循环缓存区(repl_backlog_buffer),主节点使用偏移量记录自己写到的位置(master_repl_offset ),每个从节点也使用偏移量记录自己读到的位置(slave_repl_offset );两个偏移量相减可以从缓冲区获取增量数据。
19. Redis简述主从不一致的问题?
- Redis的默认是弱一致性,异步的同步。
- 解决:
- 在配置中提供了必须有多个client连接能同步,你可以配置同步因子,趋向强一致性。
- wait 2 500:wait命令会阻塞当前客户端,直到所有先前的写入命令成功传输,并且由至少指定数量的副本(slave)确认。
20. Redis哨兵模式(简单记):
Sentinel是Redis的高可用性(HA)解决方案:由一个或多个Sentinel实例组成的Sentinel系统可以监视任意多个主服务器,以及主服务器属下的所有从服务器,当被监视的主服务器进入下线状态时,自动将下线主服务器属下的某个从服务器上级为主服务器。
21. Redis集群小点:
集群概念:
集群通过分片(sharding)来进行数据共享,并提供复制和故障转移的功能。
Redis不能保证数据的强一致性,集群在特定的条件下可能会丢失写操作。
节点通过握手,将其他节点添加到自己所处的集群当中。
Redis集群之间是如何复制的?
异步复制
Redis集群如何选择数据库?
Redis集群目前无法做数据库选择,默认在0数据库。
MOVED错误与ASK错误:
MOVED错误:在命令请求时,先检查键所在的槽是否由自己负责,不是,返回MOVED错误,MOVED错误会携带的信息,指引客户端转向至正在负责相关槽的节点。
ASK错误:在重新分片期间,数据已经从源节点迁移到目标节点,客户端连接到源节点,源节点返回ASK错误,指引客户端转向目标节点。
Redis哈希槽:
Redis集群分片使用哈希槽。
Crc16算法:根据key计算分配和存储的卡槽位置。
槽位:它是空间分配规则,它有16384个哈希槽,它还可以手工对槽位进行转移和分派(体现容错性和扩展性)。
Tips:槽位的转移和分派,Redis集群是不会自动进行的,而是需要人工配置的。所以,Redis集群的高可用是依赖于节点的主从复制与主从间的自动故障转移。
为什么是16384个哈希槽?
16384=2*1024*8,即2KB,2KB在集群心跳信息传递是不是很大,16384个槽位够用。
Redis集群至少需要几个节点?至少需要几个master节点?
Redis集群至少需要3个master节点,1master-1slave,Redis集群需要6个节点;1master-2slave,Redis集群需要9个节点,以此类推。
22. Redis集群选主过程:
Redis集群选主,基于Raft【rua父】算法的领头选举方法(leader election)实现的,从节点发现自己的主节点为失败状态(FAIL),尝试故障转移(Failover),期间会重新选主。
选主步骤:
- 从节点发现主节点变为失败状态,将自己记录集群的当前纪元(currentEpoch)加1,然后广播FAILOVER_AUTH_REQUEST信息。
- 其它节点收到广播信息后,判断请求者合法性(Epoch判断、判断Master是Fail),发送FAILOVER_AUTH_ACK,这里对每一个Epoch只发一次ACK。
- 从节点收集FAILOVER_AUTH_ACK超半数,从节点成为新的主节点,广播Pong,通知其他集群节点。
23. Reids集群中添加一个从节点同步流程:
1. 在目标从服务器上执行replicaof host port 命令(或在配置文件中配置),使该服务器变成从服务器。
2. 主服务器接收到同步请求后,执行Bgsave命令,生成RDB文件,并使用缓冲区存储起在BGSAVE命令之后,被执行的所有写命令。
3. 当RDB文件创建完毕后,主服务器会通过Socket,将RDB文件传送给从服务器。
4. 从服务器开始载入RDB文件。
5. RDB文件载入完成后,从服务器开始上线,接受命令请求。这时主服务器就会把之前存储在缓冲区的所有的写命令发送给从服务器执行。执行完缓存区所有写命令,主从数据才一致。
Tips:该过程其实就是,主从复制中的全量复制。
拓展主从重要配置:
- 无须硬盘的复制优化(RDB文件不保存到磁盘,直接Socket):repl-diskless-sync yes
- 从服务器故障下线时,主服务器配置缓存区大小,避免全量同步:repl-backlog-size 1mb
- 主从数据同步时,从服务器是否暴露老的数据:replica-serve-stale-data yes
- 降低数据不一致的概率配置等。
24. Redis集群分片逻辑:需要再总结一下
- 数据分片策略:没有使用一致性哈希,而是使用哈希槽分布数据;使用crc16(key) % 16384,计算键key属于哪个槽。
- 槽位分配:使用槽指派命令,指定节点负责一段范围的槽位。-> CLUSTER ADDSLOTS slot [slot ...]
- 相关知识点:Moved错误与Ask错误、重写分片等。
25. Redis实现分布式锁的指令?
- setnx:只有在key不存在时设置key的值
SETNX key value
- set:
SET key value EX 3600 NE
26. 为什么使用setnx ?
- 原子性操作,不存在情况下完成创建。
- 如果要做分布式锁,就要使用set key value ex ne (既要带上过期时间[ex,单位是秒],又要带上不存在[ne],避免死锁)。
27. 分布式锁实现,理论?
- 实现步骤:
- I. 在Redis设置一个唯一锁,存在key,则认为有其他客户端在使用,等待锁释放。
- II. 不存在key,没有客户端使用,可以执行任务,执行完毕,解锁,删除key。
- 存在的问题1 :获得锁后,服务宕机,由于key是唯一的,所以无法被删除。
- 解决方案:设置过期时间。
- 存在的问题2:任务执行过长,超过过期时间。
- 解决方案:通过一个守护线程,给线程续命。例如:开门狗机制。
- 存在的问题3:任务执行造成死循环,会造成无限续命。**
- 解决方案 :设置最大续命时间。
- Tips:
- 分布式锁不能用主从集群,应该是单实例、分片集群、readlock(红锁) ==> 现成技术Redisson
28. 如何解决Redis的并发竞争Key问题 -> 分布式锁
- 它是指多个系统同时对一个key进行操作,执行的顺序和我们期望的顺序不同,导致了结果的不同。
- 推荐一种方案:分布式锁(Zookeeper和Redis都可以实现分布式锁)。在实践中,当然是从以可靠性为主。所以首推Zookeeper。