对蚂蚁金服面试中几个题目的浅析

简介: 版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhaobryant/article/details/80738819 本文对今天蚂蚁金服面试中的几个问题进行简单阐述分析,望批评指正。
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhaobryant/article/details/80738819

本文对今天蚂蚁金服面试中的几个问题进行简单阐述分析,望批评指正。

搜索DAG问题

问题描述:给定一个图,寻找出里面所有的有向无环图(DAG)。

问题分析:

有向无环图

在图论中,如果一个有向图无法从某个顶点出发经过若干条边回到该点,则这个图是一个有向无环图(DAG图)。

解题思路

给定一个图,如下:

这里写图片描述

该图包括多个DAG有向无环图。

于是,对于整个算法,我们使用两个阶段来完成:

第一阶段:计算每个节点到其他节点的有向路径。为了防止成环,我们需要在合并时进行成环检测。

代码如下:

public class GraphDAGFinder {
    private Map<Node, NodeDAGList> nodeDAGListMap = new HashMap<>();

    public void findAllDAGinGraph(Set<Node> graphNodes) {
        for (Node node : graphNodes) {
            NodeDAGList dagList = this.findAllDAGbyNode(node);
            System.out.println("NODE [" + node.getId() + "] DAGS = ");
            for (NodeDAGItem item : dagList.getAllDagItems()) {
                item.printDAG();
            }
            System.out.println("-------------------------------");
        }
    }

    private NodeDAGList findAllDAGbyNode(Node n) {
        NodeDAGList dagList = this.nodeDAGListMap.get(n);
        if (dagList != null)
            return dagList;

        dagList = new NodeDAGList();
        NodeDAGItem item = new NodeDAGItem();
        item.addNode(n);
        dagList.addNodeDAGItem(item);

        if (n.getNextHops().isEmpty()) {
            return dagList;
        }

        for (Node nd : n.getNextHops()) {
            NodeDAGList tmplist = this.findAllDAGbyNode(nd);
            for (NodeDAGItem tmpit : tmplist.getAllDagItems()) {
                if (tmpit.hasNode(n))
                    continue;

                NodeDAGItem itm = tmpit.copyDAG();
                itm.addNode(n);

                dagList.addNodeDAGItem(itm);
            }
        }

        this.nodeDAGListMap.put(n, dagList);

        return dagList;
    }
}

第二阶段:路径合并成图。有了每个节点到其他节点的路径,我们可以对其所有路径进行合并,合并的规则是节点顺序不能交叉,否则会导致成环。在这里,为了合并路径,需要对不同的路径进行组合,然后再合并。

组合的代码如下,主要是寻找出对应路径集合的ID组合:

    private static Set<List<Integer>> computeCombs(List<Integer> idxs) {
        Set<List<Integer>> combinations = new HashSet<>();
        List<Integer> comb = new ArrayList<>();
        for (int i = 1; i < idxs.size(); i++) {
            getNCombs(nodes, 0, i, comb, combinations);
        }
        return combinations;
    }

    private static void getNCombs(List<Integer> idxs, int index, int len, List<Integer> comb, Set<List<Integer>> combinations) {
        if (len == 0) {
            combinations.add(comb);
            return;
        }

        if (index == idxs.size())
            return;

        comb.add(idxs.get(index));
        getNCombs(idxs, index + 1, len - 1, comb, combinations);
        comb.remove(idxs.get(index));
        getNCombs(idxs, index + 1, len, comb, combinations);
    }

合并流程如下:

从源节点开始,所有路径向后遍历,直到出现交叉,此时,选择某一分支停止向后遍历。以此类推,直到所有分支全部停止或遍历完成。

这里的合并可能有多个结果,统一存储。

最后的结果如下所示:

这里写图片描述

后续工作

对于整个问题,我们这里采用了两阶段的处理过程,能够得到结果,但是对于大规模节点图,仍然存在时间复杂度较高的问题。因此,后续工作可以围绕如何进一步降低搜索空间的方式来进行进一步的优化。比如,换一个维度,从边入手,而不是从节点入手;又如,使用回溯非递归+全局变量存储的方式来代替现有的递归方案,从而进一步减少栈溢出错误;再如,查阅论文文献,参考别人的算法,理解吃透优化。

脑裂问题

摘自CSDN博客:

在高可用HA系统中,当联系两个节点的心跳线断开时,原本为一个整体的动作协调的HA系统,就会分裂成为两个独立的个体。这时,由于两个节点相互失去了联系,都以为是对方出现了故障,两个节点上的HA软件就会像裂脑人一样,争夺共享资源,争相提供应用服务,这个时候就会出现严重后果:

  • 共享资源被瓜分,两个节点的服务都起不来;
  • 两个节点的服务都起来了,但同时读写共享资源,导致数据损坏。

一般来说,脑裂问题产生的原因主要包括下面几个:

  • 高可用服务器之间的心跳线发生故障,导致无法正常通信;
  • 高可用服务器开启了iptables防火墙,阻挡了心跳消息传输;
  • 高可用服务器上网卡地址等信息配置不正确,导致发送心跳消息失败。

可以认为,在集群或者主备模式下,由于网络原因导致节点之间不可达,此时,每个网络分区就会自主选择出master节点,从而造成原来的集群存在多个master节点。这些master节点会争夺共享资源,从而导致系统出现服务不可用或资源损坏等问题。

解决方案:

  1. 添加冗余的心跳线,如双心跳线,尽量减少“脑裂”的发生几率。
  2. 设置仲裁机制,当心跳线完全断开时,两个节点相互ping一下参考IP,不通则表示断点就出在本端,此时可自动重启,从而彻底释放可能还占用的共享资源。
  3. 增加节点至奇数个,通过raft或paxos协议来进行投票选举主节点。
目录
相关文章
|
5天前
|
存储 前端开发 JavaScript
【面试题】Promise只会概念远远不够,还需这17道题目巩固!
【面试题】Promise只会概念远远不够,还需这17道题目巩固!
|
3天前
|
运维 Linux Docker
Docker笔记(个人向) 简述,最新高频Linux运维面试题目分享
Docker笔记(个人向) 简述,最新高频Linux运维面试题目分享
|
3天前
|
程序员 Python
Job for supervisor,2024年最新b站面试题目
Job for supervisor,2024年最新b站面试题目
|
3天前
|
存储 缓存 JavaScript
web前端常见的面试题汇总(一),web前端面试题目
web前端常见的面试题汇总(一),web前端面试题目
|
3天前
|
存储 Java Shell
【Python学习教程】Python函数和lambda表达式_6(1),2024蚂蚁金服面试题及答案
【Python学习教程】Python函数和lambda表达式_6(1),2024蚂蚁金服面试题及答案
|
4天前
|
Web App开发 JavaScript Android开发
webRTC(十五),2024最新Android中级面试题目汇总解答
webRTC(十五),2024最新Android中级面试题目汇总解答
|
4天前
|
前端开发 JavaScript 开发工具
4(1),阿里面试官,前端开发面试题目
4(1),阿里面试官,前端开发面试题目
|
4天前
|
JavaScript 前端开发 Go
经典面试题目
经典面试题目
10 0
|
5天前
|
数据可视化 数据挖掘 Python
Matplotlib与Seaborn在Python面试中的可视化题目
【4月更文挑战第16天】本文介绍了Python数据可视化在面试中的重点,聚焦于Matplotlib和Seaborn库。通过基础绘图、进阶图表、图形定制和交互式图表的实例展示了常见面试问题,并列出了一些易错点,如忽视图形清晰度、误用色彩等。建议理解两者功能并注意保持图形简洁,以提升面试表现和数据可视化能力。
24 3
|
5天前
|
算法 索引
【数据结构】10道经典面试题目带你玩转链表
【数据结构】10道经典面试题目带你玩转链表
93 0