1. 程式人生 > 其它 >頭條數倉模型開發工程師 -麵筋一

頭條數倉模型開發工程師 -麵筋一

技術標籤:麵筋哥大資料資料倉庫

uid tm

u1 10:00:05
u1 10:00:10
u1 10:00:15

u1 10:20:00
u2 10:31:00

求:超過2min算不線上,統計停留時長
解:分組排序,表自關聯,交叉錯位相減

select
a.uid,
a.start_tm,
a.start_tms,
a.rank,
(end_tms-start_tm) as stop_tms,
case (end_tms-start_tm) > 120000 then 1 else 0 as morn_2mins_flag
from
(
select
uid,
tm as start_tm,
unix_timestamp™ as start_tms,

row_number() over(partition by uid order by unix_timestamp™) as rank
from
tmp.data
) a
left join
(
select
uid,
tm,
tms,
rank
from
(
select
uid,
tm as end_tm,
unix_timestamp™ as end_tms,
row_number() over(partition by uid order by unix_timestamp™) as rank
from
tmp.data
) b
where b.rank > 1
) b
on a.uid = b.uid and a,rank = (b.rank - 1)

6.資料格式如下
empid dt is_work
e1 2019-11-01 1
e1 2019-11-02 1
e1 2019-11-03 1
e1 2019-11-04 1
e1 2019-11-06 1
e2 2019-11-03 1
e2 2019-11-04 1
e2 2019-11-05 1
e3 2019-11-03 1
e3 2019-11-04 1
e3 2019-11-05 1

求:判斷連續打卡4天的員工

連續時間判斷有個技巧就是排序後的數減去指定時間下的一個差值,最後這個值,如果連續的那麼這個值是一樣的,如果不連續就不一樣

select
uid
,diff_value
,min(login_date) as login_date_min

,max(login_date) as login_date_max
,count(1) as nums
from
(
select
uid
,login_date
,((row_number() over(partition by uid order by login_date)) - datediff(login_date,‘2020-10-01’)) diff_value
from
test
) tmps
group by
uid
,diff_value

7.資料格式如下:
uid play_tm
u1 5
u2 3
u3 10
u4 15
u5 7

求:計算累計時長與總時長及其排名,類似以下
uid play_tm rank inc_tm sum_tm
u4 15 1 15 40
u3 10 2 25 40
u5 7 3 32 40
u1 5 4 37 40
u2 3 5 40 40

select
uid,
play_tm,
rank,
sum(play_tm) over(partition by 1 order by rn asc rows between unbounded preceding and current row) as inc_tm
from
(
select
uid,
paly_tm,
sum(play_tm) over(partition by uid order by paly_tm decs) as rank
from
data
) a

t1
userid,user_name
1,a
2,b
3,c

t2
userid,city
1,北京
1,上海

求有過出行記錄但沒有去過北京的使用者name

select
userid,
name,
concat_ws(’,’,collect_list(city)) as city_info_list
from
(
select
userid,
name
from
t1
) a
inner join
(
select
userid,
city
from t2
) b
on a.userid = b.userid
group by
userid,
name
having city_info_list not like “%北京%”

資料結構:

List , Set, Map都是介面,前兩個繼承至Collection介面,Map為獨立介面
Set下有HashSet,LinkedHashSet,TreeSet
List下有ArrayList,Vector,LinkedList
Map下有Hashtable,LinkedHashMap,HashMap,TreeMap
Collection介面下還有個Queue介面,有PriorityQueue類

Vector、ArrayList、LinkedList 有何區別?
Vector 是 Java 早期提供的執行緒安全的動態陣列,如果不需要執行緒安全,並不建議選擇,畢竟同步是有額外開銷的。Vector 內部是使用物件陣列來儲存資料,可以根據需要自動的增加容量,當陣列已滿時,會建立新的陣列,並拷貝原有陣列資料。
ArrayList 是應用更加廣泛的動態陣列實現,它本身不是執行緒安全的,所以效能要好很多。與 Vector 近似,ArrayList 也是可以根據需要調整容量,不過兩者的調整邏輯有所區別,Vector 在擴容時會提高 1 倍,而 ArrayList 則是增加 50%。
LinkedList 顧名思義是 Java 提供的雙向連結串列,所以它不需要像上面兩種那樣調整容量,它也不是執行緒安全的。

集合

Set:
TreeSet
LinkHashSet
HashSet

List:
ArrayList
LinkList
Vector

Queue:
LinkList
PriorityQueue

— List 有序,可重複

ArrayList
優點: 底層資料結構是陣列,查詢快,增刪慢。
缺點: 執行緒不安全,效率高
擴容:0.5倍
Vector
優點: 底層資料結構是陣列,查詢快,增刪慢。
缺點: 執行緒安全,效率低
擴容:1倍
LinkedList
優點: 底層資料結構是連結串列,查詢慢,增刪快。
缺點: 執行緒不安全,效率高
—Set 無序,唯一

HashSet
底層資料結構是雜湊表。(無序,唯一)
如何來保證元素唯一性?
1.依賴兩個方法:hashCode()和equals()
HashSet 是HashMap具體實現

LinkedHashSet
底層資料結構是連結串列和雜湊表。(FIFO插入有序,唯一)
1.由連結串列保證元素有序
2.由雜湊表保證元素唯一

TreeSet
底層資料結構是紅黑樹。(唯一,有序)

  1. 如何保證元素排序的呢?
    自然排序
    比較器排序
    2.如何保證元素唯一性的呢?
    根據比較的返回值是否是0來決定

Map

Map介面有三個比較重要的實現類,分別是HashMap、TreeMap和HashTable。

TreeMap是有序的,HashMap和HashTable是無序的。
Hashtable的方法是同步的,HashMap的方法不是同步的。這是兩者最主要的區別。
這就意味著:

Hashtable是執行緒安全的,HashMap不是執行緒安全的。
HashMap效率較高,Hashtable效率較低。
如果對同步性或與遺留程式碼的相容性沒有任何要求,建議使用HashMap。 檢視Hashtable的原始碼就可以發現,除建構函式外,Hashtable的所有 public 方法宣告中都有 synchronized關鍵字,而HashMap的原始碼中則沒有。
Hashtable不允許null值,HashMap允許null值(key和value都允許)
父類不同:Hashtable的父類是Dictionary,HashMap的父類是AbstractMap

HashTable 同步 執行緒安全
TreeMap 自然排序
LinkHashMap 插入排序

一、HashMap
hash函式:
(key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
第一步 獲取HashCode
第二部 高位參與運算
找尋陣列中位置:
h & (length-1); h = hash
//第三步 取模運算

雜湊衝突
1. 開放定址法, 發生衝突,繼續尋找下一塊未被佔用的儲存地址
2. 雜湊函式法
3. 鏈地址法 陣列+連結串列的方式

hashMap key 如何put值?

  1. key -> key.hashcode -> hash(key.hashcode) ->indexFor(h&(length-1))->獲得陣列儲存下標位置 -> 看是否有連結串列,遍歷連結串列按順序插入。h&(length-1)保證獲取的index一定在陣列範圍內
    HashMap get值
  2. key -> key.hashcode -> hash(key.hashcode) ->indexFor(h&(length-1))->獲得陣列儲存下標位置 -> 看是否有連結串列,遍歷連結串列,e.hash == hash && equals 進行比較

擴容:
當發生雜湊衝突並且size大於閾值的時候,需要進行陣列擴容,擴容時,需要新建一個長度為之前陣列2倍的新的陣列,然後將當前的Entry陣列中的元素全部傳輸過去,擴容後的新陣列長度為之前的2倍,所以擴容相對來說是個耗資源的操作

  1. 擴容後 hash 值與高位進行與運算,如果0 ,位置不變
  2. 如1,新位置為 原始位置 + 擴容前的舊容量

相關擴充套件資料:
https://tech.meituan.com/2016/06/24/java-hashmap.html

三、為何HashMap的陣列長度一定是2的次冪?
resize方法

  1. HashMap的陣列長度一定保持2的次冪,比如16的二進位制表示為 10000,那麼length-1就是15,二進位制為01111,同理擴容後的陣列長度為32,二進位制表示為100000,length-1為31,二進位制表示為011111。從下圖可以我們也能看到這樣會保證低位全為1,而擴容後只有一位差異,也就是多出了最左位的1,這樣在通過 h&(length-1)的時候,只要h對應的最左邊的那一個差異位為0,就能保證得到的新的陣列索引和老陣列索引一致(大大減少了之前已經雜湊良好的老陣列的資料位置重新調換)
  2. 陣列長度保持2的次冪,length-1的低位都為1,會使得獲得的陣列索引index更加均勻
  3. 所以說當length = 2^n時,不同的hash值發生碰撞的概率比較小,這樣就會使得資料在table陣列中分佈較均勻,查詢速度也較快。
  4. hash值新增的那個bit是1還是0就好了,是0的話索引沒變,是1的話索引變成“原索引+oldCap”,省去重新計算hash值的時間,而且同時,由於新增的1bit是0還是1可以認為是隨機的,因此resize的過程,均勻的把之前的衝突的節點分散到新的bucket了。

四、重寫equals方法需同時重寫hashCode方法
同時還要保證通過equals判斷相等的兩個物件,呼叫hashCode方法要返回同樣的整數值。而如果equals判斷不相等的兩個物件,其hashCode可以相同

五、JDK1.8中HashMap的效能優化
即當連結串列超過8時,連結串列就轉換為紅黑樹,利用紅黑樹快速增刪改查的特點提高HashMap的效能,其中會用到紅黑樹的插入、刪除、查詢等演算法。
六、HashMap Key,Value 允許資料型別

key和Value 可以為null 存陣列0位置

  1. HashMap 的 key 和 value 都可以是 null
  2. HashMap 的key只能是引用資料型別
  3. Map 的 key 和 value 都 不允許 是 基本資料型別,基本資料型別不能呼叫其hashcode()方法和equals()方法,進行比較
  4. 能為基本資料型別,可以使用基本資料型別的包裝類,例如Integer Double等。
  5. HashMap 的 key 可以是 任意物件,但如果 物件的 hashCode 改變了,那麼將找不到原來該 key 所對應的 value

七、HashMap為什麼不是執行緒安全:
1. resize(擴容)方法.
2. 不同執行緒put時,衝突
八、JDK1.8 HashMap擴容從頭插法改為尾插法:
JDK1.7 頭插法,單鏈表延伸,1.8改為紅黑樹
則是為了避免出現逆序且連結串列死迴圈的問題(JDK1.7的HashMap擴容導致死迴圈瞭解哈)。
為什麼在JDK1.7的時候是先進行擴容後進行插入,而在JDK1.8的時候則是先插入後進行擴容的呢?

二、ArrayList

擴容規則: 動態陣列擴容規則:(原始容量*3)/2 + 1

  1. ArrayList 實際上是通過一個數組去儲存資料的。當我們構造ArrayList時;若使用預設建構函式,則ArrayList的預設容量大小是10。
  2. 當ArrayList容量不足以容納全部元素時,ArrayList會重新設定容量:新的容量=“(原始容量x3)/2 + 1”。
  3. ArrayList的克隆函式,即是將全部元素克隆到一個數組中。
  4. ArrayList實現java.io.Serializable的方式。當寫入到輸出流時,先寫入“容量”,再依次寫入“每一個元素”;當讀出輸入流時,先讀取“容量”,再依次讀取“每一個元素”。

ArrayList 是一個數組佇列,相當於 動態陣列。與Java中的陣列相比,它的容量能動態增長。它繼承於AbstractList,實現了List, RandomAccess, Cloneable, java.io.Serializable這些介面。

ArrayList 繼承了AbstractList,實現了List。它是一個數組佇列,提供了相關的新增、刪除、修改、遍歷等功能。
ArrayList 實現了RandmoAccess介面,即提供了隨機訪問功能。RandmoAccess是java中用來被List實現,為List提供快速訪問功能的。在ArrayList中,我們即可以通過元素的序號快速獲取元素物件;這就是快速隨機訪問。稍後,我們會比較List的“快速隨機訪問”和“通過Iterator迭代器訪問”的效率。

ArrayList 實現了Cloneable介面,即覆蓋了函式clone(),能被克隆。 - 淺拷貝 內部元素指向記憶體地址同一個
淺拷貝:
基本型別
引用型別(記憶體地址)

ArrayList 實現java.io.Serializable介面,這意味著ArrayList支援序列化,能通過序列化去傳輸。

三、其他擴充套件容器類

JVM記憶體空間:
eg:Student stu = new Student
(1). Heap 堆空間:分配物件 new Student
(2). Stack 棧空間:臨時變數 Student stu
(3). Code 程式碼區 :類的定義,靜態資源 Student.class
上例實現步驟:
a.JVM載入Student.class 到Code區
b.new Student()在堆空間分配空間並建立一個Student例項
c.將此例項的地址賦值給引用stu, 棧空間

問題一:什麼叫垃圾回收機制?
垃圾回收是一種動態儲存管理技術,它自動地釋放不再被程式引用的物件,按照特定的垃圾收集演算法來實現資源自動回收的功能。當一個物件不再被引用的時候,記憶體回收它佔領的空間,以便空間被後來的新物件使用,以免造成記憶體洩露。

問題二:java的垃圾回收有什麼特點?
Java語言不允許程式設計師直接控制記憶體空間的使用。記憶體空間的分配和回收都是由JRE負責在後臺自動進行的,尤其是無用記憶體空間的回收操作(garbagecollection,也稱垃圾回收),只能由執行環境提供的一個超級執行緒進行監測和控制。

問題三:垃圾回收器什麼時候會執行?
一般是在CPU空閒或空間不足時自動進行垃圾回收,而程式設計師無法精確控制垃圾回收的時機和順序等。、

問題四:什麼樣的物件符合垃圾回收條件?
當沒有任何獲得執行緒能訪問一個物件時,該物件就符合垃圾回收條件。

問題五:垃圾回收器是怎樣工作的?
垃圾回收器如發現一個物件不能被任何活執行緒訪問時,他將認為該物件符合刪除條件,就將其加入回收佇列,但不是立即銷燬物件,何時銷燬並釋放記憶體是無法預知的。垃圾回收不能強制執行,然而java提供了一些方法(如:System.gc()方法),允許你請求JVM執行垃圾回收,而不是要求,虛擬機器會盡其所能滿足請求,但是不能保證JVM從記憶體中刪除所有不用的物件。

問題六:一個java程式能夠耗盡記憶體嗎?
可以。垃圾收集系統嘗試在物件不被使用時把他們從記憶體中刪除。然而,如果保持太多活動物件,系統則可能會耗盡記憶體。垃圾回收器不能保證有足夠的記憶體,只能保證可用記憶體儘可能的得到高效的管理。

問題七:程式中的資料型別不一樣儲存地方也不一樣,原生資料型別儲存在java棧中,方法執行結束就會消失;物件型別儲存在Java堆中,可以被共享,不一定隨著方法執行結束而消失。

問題八:如何檢測垃圾?(垃圾檢測機制)

 垃圾收集器的兩個任務:正確檢測出垃圾物件和釋放垃圾物件佔用的記憶體空間,而前者是關鍵所在。

 垃圾收集器有一個根物件集合,包含的元素:1)方法中區域性變數的引用;2)Java操作棧中的物件引用;3)常量池中的物件引用;4)本地方法持有的物件引用;5)類的class物件。

 JVM在垃圾回收的時候會檢查堆中的所有物件是否會被根物件直接或間接的引用,能夠被根物件到達的叫做活動物件,否則叫做非活動物件可以被回收。

記憶體回收 - GC 原理
jvm記憶體回收採用的是基於分代的垃圾收集演算法
把物件分為年青代(Young)、年老代(Tenured)、持久代(Perm),對不同生命週期的物件使用不同的演算法。(基於物件生命週期分析)

常用的垃圾回收演算法有三種,分別是標記-清除演算法、複製演算法、標記-整理演算法
標記-清除演算法:
標記階段:首先,通過根節點,標記所有從根節點開始的可達物件。未被標記的物件就是未被引用的垃圾物件;

清除階段:然後,清除所有未被標記的物件。

標記-清除演算法的缺點:
首先,它的缺點就是效率比較低(遞迴與全堆物件遍歷),暫停程式stop the world的時間比較長。(尤其對於互動式的應用程式來說簡直是無法接受。試想一下,如果你玩一個網站,這個網站一個小時就掛五分鐘,你還玩嗎?)
第二則是這種方式清理出來的空閒記憶體不連續,這點不難理解,我們的死亡物件都是隨即的出現在記憶體的各個角落的,現在把它們清除之後,記憶體的佈局自然會亂七八糟。而為了應付
複製演算法(適用於年輕代GC)
概念:記憶體空間分為兩塊,每次只使用其中一塊,在垃圾回收時,將正在使用的記憶體中的存活物件複製到未使用的記憶體塊中,之後,清除正在使用的記憶體塊中的所有物件,交換兩個記憶體的角色,完成垃圾回收。
與標記-清除演算法相比,複製演算法是一種相對高效的回收方法,且記憶體連續。
不適用於存活物件較多的場合,如老年代(複製演算法適合做新生代的GC)
優點:實現簡單,執行高效,記憶體連續。每次只要一動指標,就可聯絡分配記憶體存放複製過來的物件。

缺點:空間浪費,只用了一半記憶體,所以,要想用複製演算法,最起碼物件的存活率要非常低才行,而且最重要的是要克服50%記憶體的浪費。

MR原理(https://www.cnblogs.com/tieandxiao/p/8807475.html):
https://www.cnblogs.com/yx-zhang/p/9572221.html

Map階段
Map端Shuffle
Reduce端Shuffle
Reduce階段
Map任務處理

Reduce端:

1、Copy階段:Reducer通過Http方式得到輸出檔案的分割槽。

reduce端可能從n個map的結果中獲取資料,而這些map的執行速度不盡相同,當其中一個map執行結束時,reduce就會從JobTracker中獲取該資訊。map執行結束後TaskTracker會得到訊息,進而將訊息彙報給  JobTracker,reduce定時從JobTracker獲取該資訊,reduce端預設有5個數據複製執行緒從map端複製資料。

2、Merge階段:如果形成多個磁碟檔案會進行合併

從map端複製來的資料首先寫到reduce端的快取中,同樣快取佔用到達一定閾值後會將資料寫到磁碟中,同樣會進行partition、combine、排序等過程。如果形成了多個磁碟檔案還會進行合併,最後一次合併的結果作為reduce的輸入而不是寫入到磁碟中。

3、Reducer的引數:最後將合併後的結果作為輸入傳入Reduce任務中。(注意:當Reducer的輸入檔案確定後,整個Shuffle操作才最終結束。之後就是Reducer的執行了,最後Reducer會把結果存到HDFS上。)

/

2.2 對多個map的輸出進行合併、排序。覆蓋reduce函式,接收的是分組後的資料,實現自己的業務邏輯, <hello,2> <me,1> <you,1>

處理後,產生新的<k,v>輸出。

2.3 對reduce輸出的<k,v>寫到HDFS中。

///追加

partition過程

1,計算(key,value)所屬與的分割槽。

當map輸出的時候,寫入快取之前,會呼叫partition函式,計算出資料所屬的分割槽,並且把這個元資料儲存起來。

2,把屬與同一分割槽的資料合併在一起。

當資料達到溢位的條件時(即達到溢位比例,啟動執行緒準備寫入檔案前),讀取快取中的資料和分割槽元資料,然後把屬與同一分割槽的資料合併到一起。

yarn的三大排程策略

FIFO Scheduler把應用按提交的順序排成一個佇列,這是一個先進先出佇列,在進行資源分配的時候,先給佇列中最頭上的應用進行分配資源,待最頭上的應用需求滿足後再給下一個分配,以此類推。

Capacity(容量)排程器,有一個專門的佇列用來執行小任務,但是為小任務專門設定一個佇列會預先佔用一定的叢集資源,這就導致大任務的執行時間會落後於使用FIFO排程器時的時間。

在Fair(公平)排程器中,我們不需要預先佔用一定的系統資源,Fair排程器會為所有執行的job動態的調整系統資源。當第一個大job提交時,只有這一個job在執行,此時它獲得了所有叢集資源;當第二個小任務提交後,Fair排程器會分配一半資源給這個小任務,讓這兩個任務公平的共享叢集資源。

需要注意的是,在下圖Fair排程器中,從第二個任務提交到獲得資源會有一定的延遲,因為它需要等待第一個任務釋放佔用的Container。小任務執行完成之後也會釋放自己佔用的資源,大任務又獲得了全部的系統資源。最終的效果就是Fair排程器即得到了高的資源利用率又能保證小任務及時完成。

MapReduce

10.用mapreduce怎麼處理資料傾斜問題

資料傾斜:map /reduce程式執行時,reduce節點大部分執行完畢,但是有一個或者幾個reduce節點執行很慢,導致整個程式的處理時間很長,這是因為某一個key的條數比其他key多很多(有時是百倍或者千倍之多),這條key所在的reduce節點所處理的資料量比其他節點就大很多,從而導致某幾個節點遲遲執行不完,此稱之為資料傾斜。

(1)區域性聚合加全域性聚合。

第一次在 map 階段對那些導致了資料傾斜的 key 加上 1 到 n 的隨機字首,這樣本來相

同的 key 也會被分到多個 Reducer 中進行區域性聚合,數量就會大大降低。

第二次 mapreduce,去掉 key 的隨機字首,進行全域性聚合。

思想:二次 mr,第一次將 key 隨機雜湊到不同 reducer 進行處理達到負載均衡目的。第

二次再根據去掉 key 的隨機字首,按原 key 進行 reduce 處理。

這個方法進行兩次 mapreduce,效能稍差。

(2)增加 Reducer,提升並行度

JobConf.setNumReduceTasks(int)

(3)實現自定義分割槽

根據資料分佈情況,自定義雜湊函式,將 key 均勻分配到不同 Reducer

11.shuffle 階段,怎麼理解的

shuffle: 洗牌、發牌——(核心機制:快取,資料分割槽,排序,Merge進行區域性value的合併);

具體來說:就是將maptask輸出的處理結果資料,分發給reducetask,並在分發的過程中,對資料按key進行了分割槽和排序;

1)Map 方法之後 Reduce 方法之前這段處理過程叫 Shuffle

2)Map 方法之後,資料首先進入到分割槽方法,把資料標記好分割槽,然後把資料傳送到 環形緩衝區;環形緩衝區預設大小 100m,環形緩衝區達到 80%時,進行溢寫;溢寫前對數 據進行排序,排序按照對 key 的索引進行字典順序排序,排序的手段快排;溢寫產生大量溢 寫檔案,需要對溢寫檔案進行歸併排序;對溢寫的檔案也可以進行 Combiner 操作,前提是彙總操作,求平均值不行。最後將檔案按照分割槽儲存到磁碟,等待 Reduce 端拉取。

3)每個 Reduce 拉取 Map 端對應分割槽的資料。拉取資料後先儲存到記憶體中,記憶體不夠 了,再儲存到磁碟。拉取完所有資料後,採用歸併排序將記憶體和磁碟中的資料都進行排序。

在進入 Reduce 方法前,可以對資料進行分組操作。

12.Mapreduce 的 map 數量 和 reduce 數量是由什麼決定的 ,怎麼配置

map的數量由輸入切片的數量決定,128M切分一個切片,只要是檔案也分為一個切片,有多少個切片就有多少個map Task。

reduce數量自己配置。

Spark提交流程:
1、構建Spark Application的執行環境,啟動SparkContext
2、SparkContext向資源管理器(可以是Standalone,Mesos,Yarn)申請執行Executor資源
3、啟動StandaloneExecutorbackend
4、Executor向SparkContext申請Task
5、SparkContext將應用程式分發給Executor
6、SparkContext構建成DAG圖,將DAG圖分解成Stage、將Taskset傳送給Task Scheduler
7、最後由Task Scheduler將Task傳送給Executor執行
8、Task在Executor上執行,執行完釋放所有資源

什麼是DAG:
在 Spark 中, 使用 DAG 來描述我們的計算邏輯。

DAG 是一組頂點和邊的組合。頂點代表了 RDD, 邊代表了對 RDD 的一系列操作。

DAG Scheduler 會根據 RDD 的 transformation 動作,將 DAG 分為不同的 stage,每個 stage 中分為多個 task,這些 task 可以並行執行。

Docker專題:
什麼Docker?

答:Docker是一個容器化平臺,它以容器的形式將您的應用程式及其所有依賴項打包在一起,以確保您的應用程式在任何環境中無縫執行。
2、Docker與虛擬機器的不同點在哪裡?

答:Docker不是虛擬化方法。它依賴於實際實現基於容器的虛擬化或作業系統級虛擬化的其他工具。為此,Docker最初使用LXC驅動程式,然後移動到libcontainer現在重新命名為runc。Docker主要專注於在應用程式容器內自動部署應用程式。應用程式容器旨在打包和執行單個服務,而系統容器則設計為執行多個程序,如虛擬機器。因此,Docker被視為容器化系統上的容器管理或應用程式部署工具。

3、Docker容器有幾種狀態?

答:有四種狀態:執行、已暫停、重新啟動、已退出。

4、Dockerfile中最常見的指令是什麼?

答:FROM:指定基礎映象;LABEL:功能是為映象指定標籤;RUN:執行指定的命令;CMD:容器啟動時要執行的命令。

5、Dockerfile中的命令COPY和ADD命令有什麼區別?

答:一般而言,雖然ADD並且COPY在功能上類似,但是首選COPY。

那是因為它比ADD更易懂。COPY僅支援將本地檔案複製到容器中,而ADD具有一些功能(如僅限本地的tar提取和遠端URL支援),這些功能並不是很明顯。因此,ADD的最佳用途是將本地tar檔案自動提取到映象中,如ADD rootfs.tar.xz /。

6、什麼是Docker映象?

答:Docker映象是Docker容器的原始碼。換句話說,Docker映象用於建立容器。使用build命令建立映象,並且在使用run啟動時它們將生成容器。映象儲存在Docker登錄檔中,registry.hub.docker.com因為它們可能變得非常大,映象被設計為由其他映象層組成,允許在通過網路傳輸映象時傳送最少量的資料。

7、解釋基本的Docker使用工作流程是怎樣的?

答:(1)從Dockerfile開始,Dockerfile是映象的原始碼;(2)建立Dockerfile後,可以構建它以建立容器的映象。影象只是“原始碼”的“編譯版本”,即Dockerfile;(3)獲得容器的映象後,應使用登錄檔重新分發容器。登錄檔就像一個git儲存庫,可以推送和拉取映象;接下來,可以使用該影象來執行容器。在許多方面,正在執行的容器與虛擬機器(但沒有虛擬機器管理程式)非常相似。

Spark VS MapReduce:
Spark 基於記憶體迭代計算
Spark RDD失敗可快速從父RDD恢復
Spark更優的任務排程,DAG

1 spark中count(distinct) 的原理是什麼?
使用map運算元把元素轉為一個帶有null的元組;使用reducebykey對具有相同key的元素進行統計;之後再使用map運算元,取得元組中的單詞元素,實現去重的效果。
map(x => (x, null)).reduceByKey((x, y) => x, numPartitions).map(_._1)

2.spark消費kafka中資料時使用的reciver模式與direct模式的區別?
reciver是一直有一個task監聽著kafka的訊息,是被動的消費訊息,reciver模式kafka不自己管理消費的偏移量offset,而是由zookeeper管理,這樣容易造成消費的錯誤(提交消費偏移量時出錯,那麼offset就沒有及時更新),reciver下從kafka讀來的資料一個一個batch,bacth裡是一個一個block,最後到Rdd裡,Rdd中的一個partition就對應一個block
direct模式是主動的去kafka拿取資料,且direct模式下,spark自己管理offset(存記憶體,也可以checkpoint到hdfs),spark讀取kafka的partition與DStream中Rdd的partition對應一致

3.java中HashMap的key值是那種型別?物件可不可作為key值?
key 可以為Null
key只能是引用型別,不能是基本型別
物件是可以作為key的,如string就是物件,至於其他的物件需要實現裡面方法 即是需要重寫hashCode和equals方法
查詢key的順序:
1.呼叫hashCode()計算物件的HashCode,看是否存在表中
2.如果存在表中,則呼叫equals()判斷物件是否相同

4.hbase是寫的快還是讀的快?
hbase是寫的快,因為寫直接就往memstore裡寫,不用考慮其他,即使要往HLog裡寫,也是先經過memstore再到HLog
對於讀,一般是先從memstore裡讀取,如果沒有,再根據meta表裡記錄的表所處的region資訊再取查詢對應的region上的資料,綜合來看,是寫的快
1. Hbase寫入速度比讀取速度要快,根本原因LSM儲存引擎
2. 就是假定記憶體足夠大,因此不需要每次有資料更新就必須將資料寫入到磁碟中,而可以先將最新的資料駐留在記憶體中,等到積累到最後多之後,再使用歸併排序的方式將記憶體內的資料合併追加到磁碟隊尾
3. HBase讀取首先會在快取(BlockCache)中查詢,它採用了LRU(最近最少使用演算法),如果快取中沒找到,會從記憶體中的MemStore中查詢,只有這兩個地方都找不到時,才會載入HFile中的內容,而上文也提到了讀取HFile速度也會很快,因為節省了尋道開銷。

delta lake

spark sql 執行原理:

核心用到了Catalyst 框架

  1. 呼叫Parser 模組將 SQL 抽象轉換為AST 語法樹

  2. 呼叫Analysis 模組,及模式匹配 對樹上每個節點進行繫結解析轉換

  3. 呼叫Optimizer: 規則和 成本優化
    3.1 謂詞下推
    3.2 列裁剪
    3.3 連線重排序
    3.4 常量累加
    3.5 成本優化 多個邏輯執行計劃 結合資料分佈選出最優解

  4. 轉物理執行計劃

flink-sql 解析過程:

  1. 使用者使用對外提供Stream SQL的語法開發業務應用
  2. 用calcite對StreamSQL進行語法檢驗,語法檢驗通過後,轉換成calcite的邏輯樹節點;最終形成calcite的邏輯計劃
  3. 採用Flink自定義的優化規則和calcite火山模型、啟發式模型共同對邏輯樹進行優化,生成最優的Flink物理計劃
  4. 對物理計劃採用janino codegen生成程式碼,生成用低階API DataStream 描述的流應用,提交到Flink平臺執行

flink waterMark

flink 延遲資料處理:

1. 直接將遲到的資料丟棄
2. 將遲到的資料輸出到單獨的資料流中,即使用sideOutputLateData(new OutputTag<>())實現側輸出
3. 根據遲到的事件更新併發出結果

Flink VS SparkStreaming

Flink 是標準的實時處理引擎,基於事件驅動。而 Spark Streaming 是微批(Micro-Batch)的模型。

  1. 架構模型
    Spark Streaming 在執行時的主要角色包括:Master、Worker、Driver、Executor,Flink 在執行時主要包含:Jobmanager、Taskmanager和Slot。
  2. 任務排程
    Spark Streaming 連續不斷的生成微小的資料批次,構建有向無環圖DAG,Spark Streaming 會依次建立 DStreamGraph、JobGenerator、JobScheduler。
    Flink 根據使用者提交的程式碼生成 StreamGraph,經過優化生成 JobGraph,然後提交給 JobManager進行處理,JobManager 會根據 JobGraph 生成 ExecutionGraph,ExecutionGraph 是 Flink 排程最核心的資料結構,JobManager 根據 ExecutionGraph 對 Job 進行排程。
  3. 時間機制
    Spark Streaming 支援的時間機制有限,只支援處理時間。Flink 支援了流處理程式在時間上的三個定義:處理時間、事件時間、注入時間。同時也支援 watermark 機制來處理滯後資料。
  4. 容錯機制
    對於 Spark Streaming 任務,我們可以設定 checkpoint,然後假如發生故障並重啟,我們可以從上次 checkpoint 之處恢復,但是這個行為只能使得資料不丟失,可能會重複處理,不能做到恰一次處理語義。
    Flink 則使用兩階段提交協議來解決這個問題

slot和parallelism關係
1.slot是靜態的概念,是指taskmanager具有的併發執行能力

2.parallelism是動態的概念,是指程式執行時實際使用的併發能力

3.設定合適的parallelism能提高運算效率,太多了和太少了都不行

4.設定parallelism有多中方式,優先順序為api>env>p>file

工廠模式:
工廠是建立型模式,它的作用就是建立物件

策略模式:
策略是行為型模式,它的作用是讓一個物件在許多行為中選擇一種行為;
原則就是:分離變化部分,封裝介面,基於介面程式設計各種功能。此模式讓行為的變化獨立於演算法的使用者。