天天看點

阿裡面試-2019

還有一篇可以看看:随筆分類 - 備戰阿裡

 他媽 辛辛苦苦準備了2個月,真正的去阿裡面試的時候,簡直就是打臉大會啊,面試官的問題都聽不明白,回答更是天方夜譚。。。。。。

 以下是本人 2019年面試阿裡的題目:

自我介紹環節:

 問題1:上來就講細節,其實對方根本聽不懂,應該先介紹項目背景,如果對方感興趣的話,會多問幾句,不要自己上來就說細節。除非對方明确要求問。

 問題2:對于自己項目的架構圖一定要牢記,面試一般都會讓你畫一下架構圖,最好漂亮點,去網上查查名詞,吹一吹,唬唬人,多做點功課,因為這個可以說是送分題,哪個面試官都會問,準備一定用的上的。

問題3:對于項目建議美團的項目要重點寫,其他的簡單點寫,這樣讓面試官問起來好問點,不然隻能問自我評價的東西了。

最重要的源碼一定要看點,

這兩天阿裡面試官問了我幾個問題。 

3、MYSQL資料庫隔離級别:

Mysql的隔離級别預設是 可重複讀,REPEAT-READ

Oracle和SQL Server的預設隔離級别是:read-commit;

MySQL資料庫為我們提供的四種隔離級别:

資料庫事務的四大特性以及4種事務的隔離級别-以及對應的5種JDBC事務隔離級别

4、IO複用,什麼是IO複用,以及應用

 這個問題也比較複雜:

另一個面試官還問到IO與NIO的差別:

參考: IO多路複用,同步,異步,阻塞和非阻塞 差別

Java NIO:IO與NIO的差別 -阿裡面試題

5、資料庫遇到性能問題如何處理,

(1) 硬體提升:容量不足,磁盤不足,使用share memory

(2) 軟體提升:性能不夠,可以使用分庫,分表,讀寫分離

(3)分布式部署:一個事務,兩個資料庫關聯。使用分布式事務。 

參考:FULL GC分析過程分享

 分布式部署問題:

1、(a)一緻性Hash算法解釋

答:這是dubbo 的負載均衡的算法:ConsistentHash LoadBalance:一緻性Hash政策,具體配置方法可以參考Dubbo文檔。相同調用參數的請求會發送到同一個服務提供方節點上,如果某個節點發生故障無法提供服務,則會基于一緻性Hash算法映射到虛拟節點上(其他服務提供方)

(b) 阿裡還問 如果有7台伺服器給你提供接口,伺服器如何找到這個接口的,其實考察的是負載均衡算法:

Dubbo架構内置提供了4種負載均衡政策,如下所示:

(1)Random LoadBalance:随機政策,配置值為random。可以設定權重,有利于充分利用伺服器的資源,高配的可以設定權重大一些,低配的可以稍微小一些

(2)RoundRobin LoadBalance:輪詢政策,配置值為roundrobin。

(3)LeastActive LoadBalance:配置值為leastactive。根據請求調用的次數計數,處理請求更慢的節點會受到更少的請求

(4)ConsistentHash LoadBalance:一緻性Hash政策,具體配置方法可以參考Dubbo文檔。相同調用參數的請求會發送到同一個服務提供方節點上,如果某個節點發生故障無法提供服務,則會基于一緻性Hash算法映射到虛拟節點上(其他服務提供方)

具體參考:Dubbo學習(二) Dubbo 叢集容錯模式-負載均衡模式

2、CAP理論

 參考:CAP原則 (阿裡)

3、原子操作 AtomicInteger  

對CAS的了解,CAS是一種無鎖算法,CAS有3個操作數,記憶體值V,舊的預期值A,要修改的新值B。當且僅當預期值A和記憶體值V相同時,将記憶體值V修改為B,否則什麼都不做。 

4、分布式如何解決一緻性問題

參考:分布式系統一緻性問題解決實戰(阿裡)

6、高并發綜合政策

參考:高并發&高可用系統的常見應對政策 秒殺等-(阿裡)

  7、我說用過docker ,他問 給你5台伺服器 如何部署docker,自動化 如何寫腳本 使用 Swarm ,compose;

參考:docker swarm和compose 的使用(阿裡)

   8 docker網牆原理;

9、如果資料量很大,如何在web層面處理這些大的資料。

10、當處理上億級别的資料的時候,在web層如何搭建架構:

參考:【系統架構】億級Web系統搭建(1):Web負載均衡(阿裡)

二、資料庫問題:

1、redis

     (a)Redis的記憶體廢棄政策

  參考:Redis的記憶體回收政策和記憶體上限

   (b)redis  的網絡架構,單線程還能實作并發量這麼高,如何實作的,為何redis使用了跳表,沒有使用B+數,因為B+樹是為了減少IO,而redis 是在記憶體裡面,是以不用B+樹

具體參考:redis為何單線程 效率還這麼高 為何使用跳表不使用B+樹做索引(阿裡)

2、redis高并發的key怎麼處理

參考:高并發架構系列:Redis并發競争key的解決方案詳解

3、redis 緩存雪崩(大量的key同時失效) 緩存擊穿如何處理:

參考:Redis緩存穿透、緩存雪崩、redis并發問題 并發競争key的解決方案 (阿裡)

4、redis 是如何找到其中的key的; mysql是如何通過索引找到key 并删除的

這其實考察的是索引的原理

Mysql 使用了B+Tree 具體參考:一步步分析為什麼B+樹适合作為索引的結構

redis 使用了跳表 複雜度O(logn) 參考:聊聊Mysql索引和redis跳表 ---redis的跳表原理 時間複雜度O(logn)(阿裡)

5、mysql 的innoDB使用的是B+Tree索引,mysiam呢使用了什麼索引(fulltext索引);

舉例來說,比如我在orderId上面 添加了索引,如果 我執行 delete tb_order where orderId='12';

mysql 如何通過index定位到這條資料,并删除的。

答: fulltext索引(全文索引) 僅可用于 MyISAM 表 ,

在MySQL中,主要有四種類型的索引,分别為:B-Tree索引,Hash索引,Fulltext索引和R-Tree索引

具體參考:一步步分析為什麼B+樹适合作為索引的結構 

差別參考:MySql的多存儲引擎架構, 預設的引擎InnoDB與 MYISAM的差別(滴滴 阿裡)

5、HIVE sql 調優

參考:Hive之——Hive SQL優化

參考:hivesql優化的深入解析

三、Sring MVC 的請求過程,一個Controller是單例還是多執行個體(答案:預設是單例的)

參考:spring的controller預設是單例還是多例

參考:Spring學習 6- Spring MVC (Spring MVC原理及配置詳解)

四、IO 通訊

  1、netty原理 

  參考:新手入門:目前為止最透徹的的Netty高性能原理和架構架構解析

     2、BIO,NIO,AIO的原理

     參考:IO複用,AIO,BIO,NIO,同步,異步,阻塞和非阻塞 差別(百度)

    3、Websocket連接配接池 原理,如何實作一個端口 實作多個并發請求的。用了哪一種連接配接池。如何你來設計連接配接池,你會考慮哪些參數,比如 過期時間等

我們使用了 GenericObjectPool 一般對象池技術 

@Override
    @RhinoBreaker
    @ApiResult
    public CityResponse execRequest(CityRequest cityRequest) {
        GenericObjectPool<WSClient> wsClientPool = null;
        WSClient wsClient = null;
        URI uri;
        Transaction transaction = Cat.newTransaction(CatConstant.TRANSACTION_WEBSOCKET_REQUEST.getKey(), CatConstant.TRANSACTION_WEBSOCKET_REQUEST.getValue());

        try {
            uri = getURI(cityRequest);
            wsClientPool = wsClientPoolCache.get(uri.toString());
            wsClient = wsClientPool.borrowObject();
            CityResponse cityResponse = send(wsClient, Collections.singletonList(cityRequest));
            if (cityResponse.isOk()) {
                transaction.setSuccessStatus();
            } else {
                transaction.setStatus("上報失敗");
            }
            return cityResponse;
        } catch (Exception e) {
            transaction.setStatus(e);
            /*網絡IO 異常 & 可重試異常 & 連接配接池擷取異常*/
            return new FailureResponse(e);
        } finally {
            if (wsClientPool != null && wsClient != null) {
                ((WebSocketImpl) wsClient.getConnection()).updateLastPong();
                wsClientPool.returnObject(wsClient);
            }
            transaction.complete();
        }
    }      

    舉例說一下 連接配接池丢棄的參數寫法。關鍵字  

連接配接池丢棄的寫法:

.removalListener((RemovalListener<String, GenericObjectPool<WSClient>>) removalNotification -> {
                    /* 連接配接池銷毀 */
                    if (removalNotification.getValue() != null) {
                        removalNotification.getValue().close();
                        LOGGER.warn("url:{} 的WebSocket連接配接池已銷毀,池數目:{}", removalNotification.getKey(), wsClientPoolCache.size());
                    }
                })      

線程池丢棄最開始的資料的寫法

這是定義:

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }      

下面是重寫:

}, (r, executor) -> {
        if (!executor.isShutdown()) {
            /* 丢棄隊列最老的資料 */
            if (executor.getQueue().poll() != null) {
                Cat.logMetricForCount(CatConstant.METRIC_DISCARD_FILE_TASK_COUNT);
            }
            executor.execute(r);
        }
    });      

   4、網絡中斷 報錯 如何處理

    5、HTTP協定的架構,http1.0,http1.1,http2.0協定的差別和聯系。

參考:HTTP/1.0和HTTP/1.1 http2.0的差別,HTTP怎麼處理長連接配接(阿裡)

五、MQ

 1、kafka 如何處理高并發的,比如一條資料進入partition之後,如何找到這條資料的。怎麼消費的,消費資料的,

參考:kafka如何實作高并發存儲-如何找到一條需要消費的資料(阿裡)

六、資料結構:

   1、hashmap的時間複雜度O(1),數組的是 O(n),連結清單也是 O(n)

       參考:HashMap, HashTable,HashSet,TreeMap 的時間複雜度 注意數組連結清單 增删改查的時間複雜度都不相同(阿裡)

   2、Hashtable繼承自Dictionary類,而HashMap繼承自AbstractMap類。但二者都實作了Map接口。hashtable的初始大小

   hashmap的初始大小,為什麼擴容因子是0.75; 以及resize的操作原理  entry 擴容完了之後,順序會颠倒嗎?

    3、冒泡排序的時間複雜度是多少,空間複雜度又是多少?

 答:空間複雜度O(1)

參考:各種排序算法的時間複雜度和空間複雜度(阿裡) 

   4、blockQueue的長度是多少。 

  5、hashMap的初始大小 16 擴容因子0.75, 原因?

參考:HashMap預設加載因子為什麼選擇0.75?(阿裡)

(a) ArrayList初始化n=10個空間擴容(n3)/2 + 1,如果不夠設定傳入的值

(b) HashMap初始化n=16空間擴容2n,在并發環境下,可能會形成環狀連結清單(擴容時可能造成)

(c) Hashtable初始化n=11空間擴容2n+1

jdk1.6ConcurrentHashMap初始化segments=16個空間每個segments是初始化一個HashEntry 擴容segments=n2

jdk1.7ConcurrentHashMap初始化segments=16個空間每個segments是初始化兩個HashEntry 擴容segments=n*2

6、 concurrentHashMap 是否是線程安全的,如何實作的?

我做了總結:使用了分段鎖的技術

 這個問題比較複雜,可以參考:

hashmap,hashTable concurrentHashMap 是否為線程安全,差別,如何實作的

而且Java1.7與Java1.8實作方式并不相同,阿裡的面試官3個都問道這個問題,他們好這口,

我整理了一下:ConcurrentHashMap原理分析(1.7與1.8)

7、hashmap 如果多線程操作的話,線程不安全,為什麼會不安全:

答案:多線程put的時候,會引起死循環,好好看看這個例子,有圖有解釋,很管用

具體原因參考:HashMap多線程并發問題分析-正常和異常的rehash1(阿裡)

   7、紅黑樹的插入和删除操作,紅黑樹的樹高,左旋右旋,用紅黑樹實作currentHashMap,紅黑樹與B+樹的差別

紅黑樹的樹高度<=2log(n+1) 時間複雜度:O(lgn)

紅黑樹:    R-B Tree,全稱是Red-Black Tree,又稱為“紅黑樹”,它一種特殊的二叉查找樹。紅黑樹的每個節點上都有存儲位表示節點的顔色,可以是紅(Red)或黑(Black)。

(4)紅黑樹的特性: 

(1)每個節點或者是黑色,或者是紅色。

(2)根節點是黑色。

(3)每個葉子節點(NIL)是黑色。 [注意:這裡葉子節點,是指為空(NIL或NULL)的葉子節點!]

(4)如果一個節點是紅色的,則它的子節點必須是黑色的。

(5)從一個節點到該節點的子孫節點的所有路徑上包含相同數目的黑節點。

紅黑樹特征,以及新增删除 參考:紅黑樹之 原理和算法詳細介紹(阿裡面試-treemap使用了紅黑樹) 紅黑樹的時間複雜度是O(lgn) 高度<=2log(n+1)1、X節點左旋-将X右邊的子節點變成 父節點 2、X節點右旋-将X左邊的子節點變成父節點

8、如果一個資料結構,需要進行深度優先的周遊,或者進行廣度優先的周遊,應該首先考慮什麼資料結構來處理

答案:

深度優先-棧

廣度優先-隊列

因為深度優先需要無路可走時按照來路往回退,正好是後進先出 就是棧

廣度優先則需要保證先通路頂點的未通路鄰接點先通路,恰好就是先進先出那就是 隊列

 六、Lock 鎖問題;

1、synchronized 如何實作 線程安全的

參考:啃碎并發(七):深入分析Synchronized原理

2、膨脹鎖的原理。 

參考:JAVA鎖的膨脹過程和優化(阿裡)

參考:JAVA鎖的優化和膨脹過程

 七、JVM記憶體問題:

1、強引用 和軟引用,弱引用(比如threadlocal),虛引用,差別,可達性算法的定義;

在JDK 1.2之後,Java對引用的概念進行了擴充,将引用分為強引用(Strong Reference)、軟引用 依次逐漸減弱。

強引用
  在程式代碼中普遍存在的,類似 Object obj = new Object() 這類引用,隻要強引用還存在,垃圾收集器永遠不會回收掉被引用的對象。

軟引用
  用來描述一些還有用但并非必須的對象。對于軟引用關聯着的對象,在系統将要發生記憶體溢出異常之前,将會把這些對象列進回收範圍之中進行第二次回收。如果這次回收後還沒有足夠的記憶體,才會抛出記憶體溢出異常。

弱引用
  也是用來描述非必需對象的,但是它的強度比軟引用更弱一些,被弱引用關聯的對象隻能生存到下一次垃圾收集發生之前。當垃圾收集器工作時,無論目前記憶體是否足夠,都會回收掉隻被弱引用關聯的對象。在JDK 1.2之後,提供了WeakReference類來實作弱引用。比如 threadlocal

虛引用
  也叫幽靈引用或幻影引用(名字真會取,很魔幻的樣子),是最弱的一種引用 關系。一個對象是否有虛引用的存在,完全不會對其生存時間構成影響,也無法通過虛引用來取得一個對象執行個體。它的作用是能在這個對象被收集器回收時收到一個系統通知。。在JDK 1.2之後,提供了PhantomReference類來實作虛引用。      

 2、垃圾回收算法:

首先問一下目前你們用的垃圾回收機制是什麼樣的:

回答:使用指令:

java -XX:+PrintFlagsFinal -version | grep :

就能看到:

uintx InitialHeapSize                          := 128981632       {product}           
    uintx MaxHeapSize                              := 2065694720      {product}           
     bool PrintFlagsFinal                          := true            {product}           
     bool UseCompressedOops                        := true            {lp64_product}      
     bool UseParallelGC                            := true            {product}           
java version "1.7.0_76"
Java(TM) SE Runtime Environment (build 1.7.0_76-b13)
Java HotSpot(TM) 64-Bit Server VM (build 24.76-b04, mixed mode)      

裡面能看到我的來及回收機制是 ParallelGC的垃圾回收機制;具體參考:JVM的垃圾回收機制 總結(垃圾收集、回收算法、垃圾回收器)

能否說幾個G1的配置參數:參考:

回答:比如使用者期望的最大停頓時間

-XX:MaxGCPauseMillis=200      

 或者使用 G1的指令:-XX:+UseG1GC

具體參考:G1相關參數

(1)CMS與G1的差別和聯系

主要的差別:G1隻有的并發标記的時候才不會stop-the-world 其他步驟都會stop-the-world; 

不要以為掌握到這個程度就行了,看看阿裡下面的問題:

(2)G1垃圾回收算法的架構,跟分代收集很不一樣,架構是怎樣的,還有就是G1如何做到時間可控的

  (a) G1雖然也把記憶體分成了這三大類,Eden(E), Suvivor(S)和Old(O), 但是在G1裡面這三大類不是泾渭分明的三大塊記憶體,G1把記憶體劃分成很多小塊, 每個小塊會被标記為E/S/O中的一個,可以前面一個是Eden後面一個就變成Survivor了。

  (b) G1其實是Garbage First的意思,垃圾優先? 不是,是優先處理那些垃圾多的記憶體塊的意思。

  (c)G1的另一個顯著特點他能夠讓使用者設定應用的暫停時間,為什麼G1能做到這一點呢?也許你已經注意到了,G1回收的第4步,它是“選擇一些記憶體塊”,而不是整代記憶體來回收,這是G1跟其它GC非常不同的一點,其它GC每次回收都會回收整個Generation的記憶體(Eden, Old), 而回收記憶體所需的時間就取決于記憶體的大小,以及實際垃圾的多少,是以垃圾回收時間是不可控的;而G1每次并不會回收整代記憶體,到底回收多少記憶體就看使用者配置的暫停時間,配置的時間短就少回收點,配置的時間長就多回收點,伸縮自如。 

更具體的參考:G1 垃圾收集器架構和如何做到可預測的停頓(阿裡)

G1與CMS的差別參考:CMS收集器和G1收集器 他們的優缺點對比 G1隻有并發标記才不會stop-the-world 其他都會停下來(阿裡多次問到)

3、當new 一個對象的時候,JVM做了那些事情。還有我們在堆配置設定了空間,那麼會不會線程不安全,因為堆是共享的?(阿裡面試的高頻問題,問了至少3次了)

回答:首先一定是安全的,至于原因:為了保證Java對象的記憶體配置設定的安全性,同時提升效率,一般有兩種解決方案:

  • 1、對配置設定記憶體空間的動作做同步處理,采用CAS機制,配合失敗重試的方式保證更新操作的線程安全性。
  • 2、每個線程在Java堆中預先配置設定一小塊記憶體,然後再給對象配置設定記憶體的時候,直接在自己這塊"私有"記憶體中配置設定,當這部分區域用完之後,再配置設定新的"私有"記憶體。
  • 方案1在每次配置設定時都需要進行同步控制,這種是比較低效的。

    方案2是HotSpot虛拟機中采用的,這種方案被稱之為TLAB配置設定,即Thread Local Allocation Buffer。這部分Buffer是從堆中劃分出來的,但是是本地線程獨享的。

    這裡值得注意的是,我們說TLAB時線程獨享的,但是隻是在“配置設定”這個動作上是線程獨占的,至于在讀取、垃圾回收等動作上都是線程共享的。而且在使用上也沒有什麼差別

  • 不知道大家有沒有想過,我們使用了TLAB之後,在TLAB上給對象配置設定記憶體時線程獨享的了,這就沒有沖突了,但是,TLAB這塊記憶體自身從堆中劃分出來的過程也可能存在記憶體安全問題啊。是以,在對于TLAB的配置設定過程,還是需要進行同步控制的。但是這種開銷相比于每次為單個對象劃分記憶體時候對進行同步控制的要低的多。

參考:靈魂拷問:Java對象的記憶體配置設定過程是如何保證線程安全的?(阿裡面試)

4、 如果遇到了Full GC如何處理,

首先搞明白什麼事Full GC ,JVM回收主要是堆的回收,而堆分為 新生代和老年代,新生代如果滿了就會執行Minor GC,回收一次新生代的記憶體,

新生代執行垃圾回收很頻繁,是以使用了複制法(Coping)

存活的對象會放在老年代,如果老年代滿了,會執行Full GC,回收老年代的垃圾不是很頻繁,是以使用了标記整理法(Mark-Compact)

由此看來:Full GC的生成條件:

(a)調用System.gc時,系統建議執行Full GC,但是不必然執行

(b)老年代空間不足

(c)方法區空間不足

(d)通過Minor GC後進入老年代的平均大小大于老年代的可用記憶體

(e)由Eden區、From Space區向To Space區複制時,對象大小大于To Space可用記憶體,則把該對象轉存到老年代,且老年代的可用記憶體小于該對象大小 

阿裡大神面試官回答:

(a)看一下有沒有大對象

(b)大的靜态對象

(c) Dump 記憶體快照,進行分析 

八、線上問題排查:

   1、如果一台伺服器負載很高,如何處理 ,假如他cpu使用率很低,IO也很低呢?

不要上來就說 看一下 是CPU高還是IO高,因為有時候,CPU不高,IO也不高,但伺服器負載就是高,看下面的部落格

參考:伺服器負載過高問題分析-不是cpu高負載也不是IO負載如何處理(阿裡)

九、算法題目

1、給你1000條資料,每條資料都帶有起始結束時間的任務,如何把時間重疊的資料取出來;

2、給你1億個資料,裡面有重複的,如何把前100最小的數取出來

參考:關于“100g檔案全是數組,取最大的100個數”解決方法彙總

十、Cache 緩存

1、guava如何删除過期資料,guava的架構,如何實作的删除,都要看源碼,别隻看部落格解說。就是應付也要看點,不然怎麼說,Caffeine緩存

參考:Guava cacha 機制及源碼分析   

2、在GuavaCache中,并不存在任何線程!它實作機制是在寫操作時順帶做少量的維護工作(如清除),偶爾在讀操作時做(如果寫操作實在太少的話),也就是說在使用的是調用線程 

參考:GuavaCache簡介(一)是輕量級的架構 少量資料,并且 過期時間相同 可以用 GuavaCache

十一、設計模式,生産者消費者設計模式,以及wait,notifiy的運用,阿裡問了一個面試、終極目的是用wait和notify實作一個可重入鎖來保證順序;

問題:使用“生産者-消費者模式”編寫代碼實作:線程A随機間隔(10~200ms)按順序生成1到100的數字(共100個),

放到某個隊列中.3個線程B、C、D即時消費這些資料,線程B列印(向控制台)所有被2整除的數,

線程C列印被3整除的數,線程D列印其它資料,要求數字的列印是有序的(從1到100)

限時40分鐘,可以使用IDE及第三方類庫

參考:阿裡筆試-生産者消費者模式

這個類似的問題美團也問過,不過美團直接說能否用synchronized 實作一個可重入鎖,本質上也是使用了wait和notify()函數

參考:使用synchronized 實作ReentrantLock(美團面試題目)

 十二、加解密算法 每次向對方的伺服器發送資料,都需要傳遞token 這是什麼機制?

這是非對稱加密 參考:聊聊對稱/非對稱加密在HTTPS中的使用

最後一百、架構設計知識

1、是否了解DDD 架構設計 

阿裡面試-2019

分為四層,(1)基礎設施層(2)領域服務層(3)應用服務層(4)使用者接口層

使用者界面層:負責向使用者展示資訊或解釋使用者指令,如:天網的前端界面,調用天網服務的外賣應用程式等。

應用層:定義軟體要完成的任務,指揮領域層的對象或調用其他應用服務來解決問題 ,不包含業務規則和知識,要求盡量的簡單。

領域層:負責表達業務概念,業務狀态資訊以及業務規則。 核心

基礎設施層:為上面各層提供通用的技術能力:比如 以上各層互動的Thrfit,為領域層提供持久化機制的zebra,公司為UI層提供的通用元件 等等。

以天網量化分級導入功能為例:

使用者界面層:天網前端界面

應用層:負責參數校驗、excel解析、調用mdc接口驗證門店是否存在、調用領域層進行檢查 和存儲。

領域層:量化分級子產品 領域對象(Entity、Value Objext)、以及 操作服務(Service)。

基礎設施層:Thrift、MCC、zebra等。

1、電面:重點在過往主導技術項目的方案闡述/計算機理論知識/Java基礎知識的考核:

(1)方案有思考、有對比選型 (2)溝通表達順暢、能抓住重點;(3)計算機(計算機網絡/資料結構/作業系統等),Java(集合類/并發/多線程/JVM等)基礎紮實 (4)有業務sense加分

2、現場1面:重點考察落地以及編碼能力(1)深入履曆核心方案深挖 (2)給一個陌生場景,考察候選人面對新問題的應變能力 (3)實際編碼考察

3、資料結構的現場面試題:

連結清單翻轉的圖文講解

參考:https://www.cnblogs.com/aspirant/p/9199608.html

給定一個字元串,請你找出其中不含有重複字元的 最長子串 的長度。

參考:https://www.jianshu.com/p/f1f74aa59dd4

參考:DDD(Domain Driven Design) 架構設計

參考:阿裡P6-P7面試準備