(2023打卡)每日两道面试题|一道算法题|7月8日

文章详细介绍了Redis的主从复制和哨兵模式,包括全量同步、增量同步的步骤以及哨兵的监控和故障恢复机制。同时,讨论了Redis的高并发和高可用性策略,并提出了防止集群脑裂的解决方案。此外,还涉及了一个使用双指针解决有序数组两数之和问题的算法题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.面试题

1.1.Redis主从复制

一般Redis集群有主从、哨兵、分片。单点Redis的并发能力是有上限的,要进一步提高Redis 的并发能力,就需要搭建主从集群,实现读写分离。

在这里插入图片描述

1.1.1.主从全量同步

Replication ID:简称replid,是数据集的标记,id一致则说明是同一数据集。每一个master都有唯一的replid,slave则会继承master节点的replid

offset:偏移量,随着记录再repl_baklog中的数据增多而逐渐增大。slave完成同步时也会记录当前同步的offset。如果salve的offset小于master的offset,说明slave数据落后于master,需要更新

在这里插入图片描述

全量同步的执行步骤

  1. 从节点发起请求给主节点想要同步数据
  2. 主节点判断是否是第一次请求(通过查看id的方式),如果是第一次请求则全量同步
  3. 主节点执行bgsave方法生成RDB文件发送给从节点去执行
  4. 主节点再记录RDB期间,接收的其他命令会存到repl_baklog文件中,然后再返回给从节点去执行

1.1.2.增量同步

主从增量同步(slave重启或后期数据变化)

在这里插入图片描述

增量同步的执行步骤

  1. 从节点发起同步请求,主节点判断是否为第一次,是第一次返回id和offset不是第一次返回continue,并且获取到从节点的offset值,主节点从repl_baklog日志文件中获取offset之后的数据同步到从节点。

面试题

Redis集群有那些方案?

介绍一下redis的主从同步

能说一下,主从同步数据的流程

答案

在这里插入图片描述

1.2.Redis哨兵模式

Redis提供了哨兵(Sentinel)机制来实现主从集群的自动故障恢复。哨兵的结构和作用如下:

在这里插入图片描述

  • 监控:Sentinel会不断检查master和slave是否按预期工作
  • 自动故障恢复:如果master故障,Sentinel会将一个slave提升为master。当故障实例恢复后也以新的master为主
  • 通知:Sentinel充当Redis客户端的服务发现来源,当集群发生故障转移时,会将最新信息推送给Redis的客户端

1.2.1.哨兵服务状态监控

Sentinel基于心跳机制检测服务状态,每隔1秒向集群的每一个实例发送ping命令:

  • 主观下线:如果某sentinel节点发现某实例未在规定时间响应,则认为该实例主观下线
  • 客观下线:若超过指定数量(quorum)的sentinel都认为该实例主观下线,则该实例客观下线。quorum值最好超过Sentinel实例数量的一半。

在这里插入图片描述

哨兵选主规则

  • 首先判断主于从节点断开时间长短,如超过指定值就派该从节点
  • 然后判断从节点的slave-priority值,值越小优先级越高
  • 如果slave-priority一样,则判断slave节点的offset值,值越大优先级越高
  • 最后是判断slave节点的运行id大小,越小优先级越高。

1.2.2.哨兵模式脑裂

由于网络原因,主(master)节点和Sentinel处于不同的网络分区,Sentinel只能检测从节点,此时Sentinel会按照选主的规则选出一个满足条件从(slave)节点作为新主(master)节点。但是老的主(master)节点还在接收客户端的消息,但是新主(master)节点没有与客户端建立连接,下图

在这里插入图片描述

当网络恢复的时候,Sentinel会将老的主(master)节点降为从(slave)节点,这个时候这个刚刚转变为slave的从节点就会去master请求数据,在此期间它会清空自己的数据,导致在脑裂之前客户端向这个节点写入的数据就被删除了,最终会造成数据丢失

在这里插入图片描述

min-replicas-to-write 1

当客户端连接主节点写数据的时候,这个主节点必须要有一个从节点才行,否则直接拒绝请求

min-replicas-max-lag 5

配置主从数据复制和同步的延迟不能超过5秒。

面试题

怎么保证Redis的高并发高可用

你们使用redis是单点还是集群,那种集群

redis的集群脑裂,如何解决

答案

在这里插入图片描述

2.算法题

在这里插入图片描述

2.1.分析:

我们得到的是一个顺序递增数组省去了排序,在数组中选择两个数的目标值此时有两种方式可以选择。

  • 暴力递归

    1. 通过两个for循环把每行每列的数字都跑一遍,如果当num[i]+num[j]大于目标值,这个时候就没必要执行j后面的值了,直接break跳出j的循环,i++下一轮
    2. 当它等于目标值的时候还要注意题目要求不能是两个索引相同的数的和比如{2,3,3,5,9} target=6,那么你的结果就只能是[2,3]而不是[2,2]或[3,3],所以j的值等于i+1这样就不可能会有相同值了。
    3. 最后答案加个一,下表是从一开始的

    但是这个方法不推荐基本达到了O(n平方)的时间复杂度了,

     public int[] twoSum(int[] numbers, int target) {
            int n=numbers.length;
            //由于是递增数组所以num[i]+num[j]>target则num[i]+num[j+1]>target
            //如果 num[i]+num[j]<target num[i-1]+num[j]<target
            for(int i=0;i<n;i++){
                for(int j=i+1;j<n;j++){
                    if(numbers[i]+numbers[j]>target){
                        break;
                    }
                    if(numbers[i]+numbers[j]==target){
                        return new int[]{i+1,j+1};
                    }
                    
                }
            }
            //因为方法的泛型是int[]所以即使找到了结果,最后还是返回个空数据
            return new int[0];
        }
        
    
  • 双指针

    1. 再初始状态下,令left指向数组第一个元素,right指向最后一个元素
    2. 进入循环,控制循环退出条件为left<right
    3. 再每次循环中,如果left与right的数字之和等于所给target,则返回当前索引值
    4. 若left与right的数字之和小于所给target,left++
    5. 若left与right的数字之和大于所给target,right–

    时间复杂度:O(n),空间复杂度:O(1)。

    public int[] twoSum(int[] numbers, int target) {
            int n=numbers.length;
            int left=0;
            int right=n-1;
            while(left<right){
                if(numbers[left]+numbers[right]==target){
                    return new int[]{left+1,right+1};
                }
                if(numbers[left]+numbers[right]>target){
                    right--;
                }
                if(numbers[left]+numbers[right]<target){
                    left++;
                }
            }
            return new int[0];
           
        }
    

2.2.使用技术重点:

双重for循环的暴力递归,双指针利用题目已经递增排好顺序的特征,左右相加来缩小范围,当然这个题使用二分查找应该是最快的因为这道题面对的数据长度和大小都是很多的,感兴趣可以上网搜二分查找

  • -1000 <= numbers[i] <= 1000
  • 2 <= numbers.length <= 3 * 104
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jacob_uln

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值