大數據面試題,唬住50k

  1. 選擇題
    1. 下面哪個程序負責 HDFS 數據存儲。

a)NameNode  b)Jobtracker  c)Datanode d)secondaryNameNode e)tasktracker

答案 C datanode

    1. HDfS 中的 block 默認保存幾份?

a)3 份 b)2 份 c)1 份 d)不確定

答案 A 默認 3 份

    1. 下列哪個程序通常與NameNode在一個節點啓動?

a)SecondaryNameNode b)DataNode c)TaskTracker d)Jobtracker

答案 D

    1. HDFS 默認 Block Size

a)32MB  b)64MB c)128MB

答案:B

    1. 下列哪項通常是集羣的最主要瓶頸

a)CPU   b)網絡 c)磁盤 IO  d)內存

答案:C 磁盤

首先集羣的目的是爲了節省成本,用廉價的 pc 機,取代小型機及大型機。小型機和大型機有什麼特點?

1.cpu 處理能力強

2.內存夠大,所以集羣的瓶頸不可能是 a 和 d

3.如果是互聯網有瓶頸,可以讓集羣搭建內網。每次寫入數據都要通過網絡(集羣是內網),然後還要寫入 3 份數據,所以 IO 就會打折扣。

    1. 關於 SecondaryNameNode 哪項是正確的?

a)它是 NameNode 的熱備     b)它對內存沒有要求

c)它的目的是幫助 NameNode 合併編輯日誌,減少 NameNode 啓動時間

d)SecondaryNameNode 應與 NameNode 部署到一個節點

答案 C。

    1. 下列哪項可以作爲集羣的管理?

a)Puppet b)Pdsh c)Cloudera Manager d)Zookeeper

答案 ABD

具體可查看什麼是 Zookeeper,Zookeeper 的作用是什麼,在 Hadoop 及 hbase 中具體作用是什麼。

    1. Client 端上傳文件的時候下列哪項正確

a)數據經過 NameNode 傳遞給 DataNode

b)Client 端將文件切分爲 Block,依次上傳

c)Client 只上傳數據到一臺 DataNode,然後由 NameNode 負責 Block 複製工作

答案 B

分析:Client 向 NameNode 發起文件寫入的請求。NameNode 根據文件大小和文件塊配置情況,返回給 Client 它所管理部分 DataNode 的信息。Client 將文件劃分爲多個 Block,根據 DataNode 的地址信息,按順序寫入到每一個DataNode 塊中。具體查看HDFS 體系結構簡介及優缺點。

    1. 下列哪個是 Hadoop 運行的模式

a)單機版 b)僞分佈式 c)分佈式

答案 ABC 單機版,僞分佈式只是學習用的。

  1. 面試題
    1.  Hadoop的核心配置是什麼?

Hadoop的核心配置通過兩個xml文件來完成:1,hadoop-default.xml;2,hadoop-site.xml。這些文件都使用xml格式,因此每個xml中都有一些屬性,包括名稱和值,但是當下這些文件都已不復存在。

    1. 那當下又該如何配置?

Hadoop現在擁有3個配置文件:1,core-site.xml;2,hdfs-site.xml;3,mapred-site.xml。這些文件都保存在conf/子目錄下。

 

    1. “jps”命令的用處?

這個命令可以檢查Namenode、Datanode、Task Tracker、 Job Tracker是否正常工作。

    1. mapreduce的原理?

 

    1.  HDFS存儲的機制?
      1. hdfs寫流程

流程:

  1. client鏈接namenode存數據
  2. namenode記錄一條數據位置信息(元數據),告訴client存哪。
  3. client用hdfs的api將數據塊(默認是64M)存儲到datanode上。
  4. datanode將數據水平備份。並且備份完將反饋client。
  5. client通知namenode存儲塊完畢。
  6. namenode將元數據同步到內存中。
  7. 另一塊循環上面的過程。
      1. 讀流程

流程:

  1. client鏈接namenode,查看元數據,找到數據的存儲位置。
  2. client通過hdfs的api併發讀取數據。
  3. 關閉連接。
    1. 舉一個簡單的例子說明mapreduce是怎麼來運行的 ?

wordcount的例子

    1. 用mapreduce來實現下面需求?

現在有10個文件夾,每個文件夾都有1000000個url.現在讓你找出top1000000url。

解答:topk

 

(還可以用treeMap, 到1000000了每來一個都加進去, 刪掉最小的)

    1. hadoop中Combiner的作用?

combiner是reduce的實現,在map端運行計算任務,減少map端的輸出數據。

作用就是優化。

但是combiner的使用場景是mapreduce的map和reduce輸入輸出一樣。

    1. 簡述hadoop安裝

    1. 請列出hadoop進程名

    1. 解決下面的錯誤

  1. 權限問題,可能曾經用root啓動過集羣。(例如hadoop搭建的集羣,是tmp/hadoop-hadoop/.....)
  2. 可能是文件夾不存在
  3. 解決: 刪掉tmp下的那個文件,或改成當前用戶
    1. 寫出下面的命令

    1. 簡述hadoop的調度器

    1. 列出你開發mapreduce的語言

java

    1. 書寫程序

wordcount

    1. 不同語言的優缺點

hadoop是java寫的,java的集成效果最好,並且平臺環境統一。

    1. hive有哪些保存元數據的方式,個有什麼特點。

  1. 內存數據庫derby,安裝小,但是數據存在內存,不穩定
  2. mysql數據庫,數據存儲模式可以自己設置,持久化好,查看方便。
    1. combiner和partition的作用

combiner是reduce的實現,在map端運行計算任務,減少map端的輸出數據。

作用就是優化。

但是combiner的使用場景是mapreduce的map輸出結果和reduce輸入輸出一樣。

 

partition的默認實現是hashpartition,是map端將數據按照reduce個數取餘,進行分區,不同的reduce來copy自己的數據。

partition的作用是將數據分到不同的reduce進行計算,加快計算效果。

    1. hive內部表和外部表的區別

內部表:加載數據到hive所在的hdfs目錄,刪除時,元數據和數據文件都刪除

外部表:不加載數據到hive所在的hdfs目錄,刪除時,只刪除表結構。

    1. hbase的rowkey怎麼創建好?列族怎麼創建比較好?

hbase存儲時,數據按照Row key的字典序(byte order)排序存儲。設計key時,要充分排序存儲這個特性,將經常一起讀取的行存儲放到一起。(位置相關性)

一個列族在數據底層是一個文件,所以將經常一起查詢的列放到一個列族中,列族儘量少,減少文件的尋址時間。

    1. 用mapreduce怎麼處理數據傾斜問題?

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

 

用hadoop程序進行數據關聯時,常碰到數據傾斜的情況,這裏提供一種解決方法。

自己實現partition類,用key和value相加取hash值:

方式1:

源代碼:

public int getPartition(K key, V value,

                          int numReduceTasks) {

    return (key.hashCode() & Integer.MAX_VALUE) % numReduceTasks;

  }

修改後

public int getPartition(K key, V value,

                          int numReduceTasks) {

    return ((key).hashCode()+value.hashCode() & Integer.MAX_VALUE) % numReduceTasks;

  }

 

方式2

public class HashPartitioner<K, V> extends Partitioner<K, V> {

private int aa= 0;

  /** Use {@link Object#hashCode()} to partition. */

  public int getPartition(K key, V value,

                          int numReduceTasks) {

    return (key.hashCode()+(aa++) & Integer.MAX_VALUE) % numReduceTasks;

  }

    1. hadoop框架中怎麼來優化

(1)  從應用程序角度進行優化。由於mapreduce是迭代逐行解析數據文件的,怎樣在迭代的情況下,編寫高效率的應用程序,是一種優化思路。

(2)  對Hadoop參數進行調優。當前hadoop系統有190多個配置參數,怎樣調整這些參數,使hadoop作業運行儘可能的快,也是一種優化思路。

(3) 從系統實現角度進行優化。這種優化難度是最大的,它是從hadoop實現機制角度,發現當前Hadoop設計和實現上的缺點,然後進行源碼級地修改。該方法雖難度大,但往往效果明顯。

(4)linux內核參數調整

 

      1. 從應用程序角度進行優化

(1) 避免不必要的reduce任務

如果mapreduce程序中reduce是不必要的,那麼我們可以在map中處理數據, Reducer設置爲0。這樣避免了多餘的reduce任務。

(2) 爲job添加一個Combiner

爲job添加一個combiner可以大大減少shuffle階段從map task拷貝給遠程reduce task的數據量。一般而言,combiner與reducer相同。

(3) 根據處理數據特徵使用最適合和簡潔的Writable類型

Text對象使用起來很方便,但它在由數值轉換到文本或是由UTF8字符串轉換到文本時都是低效的,且會消耗大量的CPU時間。當處理那些非文本的數據時,可以使用二進制的Writable類型,如IntWritable, FloatWritable等。二進制writable好處:避免文件轉換的消耗;使map task中間結果佔用更少的空間。

(4) 重用Writable類型

很多MapReduce用戶常犯的一個錯誤是,在一個map/reduce方法中爲每個輸出都創建Writable對象。例如,你的Wordcout mapper方法可能這樣寫:

 

public void map(...) {

  …

 

  for (String word : words) {

    output.collect(new Text(word), new IntWritable(1));

  }

}

這樣會導致程序分配出成千上萬個短週期的對象。Java垃圾收集器就要爲此做很多的工作。更有效的寫法是:

class MyMapper … {

  Text wordText = new Text();

  IntWritable one = new IntWritable(1);

  public void map(...) {

    for (String word: words) {

      wordText.set(word);

      output.collect(wordText, one);

    }

  }

}

(5) 使用StringBuffer而不是String

當需要對字符串進行操作時,使用StringBuffer而不是String,String是read-only的,如果對它進行修改,會產生臨時對象,而StringBuffer是可修改的,不會產生臨時對象。

      1. 對參數進行調優

查看linux的服務,可以關閉不必要的服務

ntsysv

停止打印服務

#/etc/init.d/cups stop

#chkconfig cups off

關閉ipv6

#vim /etc/modprobe.conf

添加內容

alias net-pf-10 off

alias ipv6 off

 

調整文件最大打開數

查看: ulimit -a    結果:open files (-n) 1024

臨時修改: ulimit -n 4096

持久修改:

vi /etc/security/limits.conf在文件最後加上:

* soft nofile 65535
* hard nofile 65535
* soft nproc 65535
* hard nproc 65535

修改linux內核參數

vi /etc/sysctl.conf

添加

net.core.somaxconn = 32768

#web應用中listen函數的backlog默認會給我們內核參數的net.core.somaxconn限制到128,而nginx定義的NGX_LISTEN_BACKLOG默認爲511,所以有必要調整這個值。

調整swap分區什麼時候使用:

查看:cat /proc/sys/vm/swappiness

設置:vi /etc/sysctl.conf 

            在這個文檔的最後加上這樣一行: vm.swappiness=10

            表示物理內存使用到90%(100-10=90)的時候才使用swap交換區

關閉noatime

vi /etc/fstab

/dev/sda2    /data     ext3  noatime,nodiratime  0 0

設置readahead buffer

blockdev --setra READAHEAD 512 /dev/sda

 

 

 

一下是修改mapred-site.xml文件

修改最大槽位數

槽位數是在各個tasktracker上的mapred-site.xml上設置的,默認都是2

<property>  

            <name>mapred.tasktracker.map.tasks.maximum</name>  #++++maptask的最大數

            <value>2</value>  

        </property>                  

     <property>  

            <name>mapred.tasktracker.reduce.tasks.maximum</name>  #++++reducetask的最大數

                <value>2</value>  

      </property>  

調整心跳間隔

集羣規模小於300時,心跳間隔爲300毫秒

mapreduce.jobtracker.heartbeat.interval.min  心跳時間

mapred.heartbeats.in.second  集羣每增加多少節點,時間增加下面的值

mapreduce.jobtracker.heartbeat.scaling.factor 集羣每增加上面的個數,心跳增多少

啓動帶外心跳

mapreduce.tasktracker.outofband.heartbeat  默認是false

配置多塊磁盤

mapreduce.local.dir

配置RPC hander數目

mapred.job.tracker.handler.count 默認是10,可以改成50,根據機器的能力

配置HTTP線程數目

tasktracker.http.threads  默認是40,可以改成100 根據機器的能力

選擇合適的壓縮方式

以snappy爲例:

<property>  

            <name>mapred.compress.map.output</name>

            <value>true</value>  

        </property>                  

     <property>  

            <name>mapred.map.output.compression.codec</name> 

                <value>org.apache.hadoop.io.compress.SnappyCodec</value>  

      </property>  

啓用推測執行機制

推測執行(Speculative Execution)是指在分佈式集羣環境下,因爲程序BUG,負載不均衡或者資源分佈不均等原因,造成同一個job的多個task運行速度不一致,有的task運行速度明顯慢於其他task(比如:一個job的某個task進度只有10%,而其他所有task已經運行完畢),則這些task拖慢了作業的整體執行進度,爲了避免這種情況發生,Hadoop會爲該task啓動備份任務,讓該speculative task與原始task同時處理一份數據,哪個先運行完,則將誰的結果作爲最終結果。

推測執行優化機制採用了典型的以空間換時間的優化策略,它同時啓動多個相同task(備份任務)處理相同的數據塊,哪個完成的早,則採用哪個task的結果,這樣可防止拖後腿Task任務出現,進而提高作業計算速度,但是,這樣卻會佔用更多的資源,在集羣資源緊缺的情況下,設計合理的推測執行機制可在多用少量資源情況下,減少大作業的計算時間。

mapred.map.tasks.speculative.execution  默認是true

mapred.rduce.tasks.speculative.execution  默認是true

設置是失敗容忍度

mapred.max.map.failures.percent   作業允許失敗的map最大比例  默認值0,即0%

mapred.max.reduce.failures.percent  作業允許失敗的reduce最大比例  默認值0,即0%

mapred.map.max.attemps  失敗後最多重新嘗試的次數 默認是4

mapred.reduce.max.attemps  失敗後最多重新嘗試的次數 默認是4

啓動jvm重用功能

mapred.job.reuse.jvm.num.tasks  默認值1,表示只能啓動一個task,若爲-1,表示可以最多運行數不限制

設置任務超時時間

mapred.task.timeout  默認值600000毫秒,也就是10分鐘。

合理的控制reduce的啓動時間

mapred.reduce.slowstart.completed.maps  默認值0.05  表示map任務完成5%時,開始啓動reduce任務

跳過壞記錄

 當任務失敗次數達到該值時,纔會進入skip mode,即啓用跳過壞記錄數功能,也就是先試幾次,不行就跳過

mapred.skip.attempts.to.start.skipping 默認值 2

map最多允許跳過的記錄數

mapred.skip.map.max.skip.records 默認值0,爲不啓用

reduce最多允許跳過的記錄數

mapred.skip.reduce.max.skip.records 默認值0,爲不啓用

換記錄存放的目錄

mapred.skip.out.dir  默認值${mapred.output.dir}/_logs/ 

    1. 我們開發job時,是否可以去掉reduce階段。

可以。設置reduce數爲0 即可。

    1. datanode在什麼情況下不會備份

datanode在強制關閉或者非正常斷電不會備份。

    1. combiner出現在那個過程

出現在map階段的map方法後。

    1. hdfs的體系結構

hdfs有namenode、secondraynamenode、datanode組成。

爲n+1模式

namenode負責管理datanode和記錄元數據

secondraynamenode負責合併日誌

datanode負責存儲數據

    1. 3個datanode中有一個datanode出現錯誤會怎樣?

這個datanode的數據會在其他的datanode上重新做備份。

    1. 描述一下hadoop中,有哪些地方使用了緩存機制,作用分別是什麼?

在mapreduce提交job的獲取id之後,會將所有文件存儲到分佈式緩存上,這樣文件可以被所有的mapreduce共享。

    1. 如何確定hadoop集羣的健康狀態

通過頁面監控,腳本監控。

    1. 生產環境中爲什麼建議使用外部表?

1、因爲外部表不會加載數據到hive,減少數據傳輸、數據還能共享。

2、hive不會修改數據,所以無需擔心數據的損壞

  1. 刪除表時,只刪除表結構、不刪除數據。
  1. 15期新增
    1. 新增

  1. 通過節點信息和瀏覽器查看,通過腳本監控

hadoop-deamon.sh start namenode

hdfs-deamon.sh start namenode

  1. 自己書寫腳本監控重啓
  2. 行健以字典序排列,設計時充分利用這個特點,將經常一起查詢的行健設計在一起,例如時間戳結尾,用戶名開頭(位置相關性)

  1. 用hive分析業務數據即可
  2. 將數據導入到hive中

sql的設計思路:多表關聯

  1. 找到所有在2015-01-01到2015-01-31時間內訪問A頁面的用戶
  2. 在這些用戶中刪選在2015-01-01到2015-03-31下單的用戶
  3. 統計總數
    1. 你們數據庫怎麼導入hive 的,有沒有出現問題

在導入hive的時候,如果數據庫中有blob或者text字段,會報錯,解決方案在sqoop筆記中

    1. 公司技術選型可能利用storm 進行實時計算,講解一下storm

描述下storm的設計模式,是基於work、excutor、task的方式運行代碼,由spout、bolt組成等等

    1. 一個datanode 宕機,怎麼一個流程恢復

將datanode數據刪除,重新當成新節點加入即可。

    1. Hbase 的特性,以及你怎麼去設計 rowkey 和 columnFamily ,怎麼去建一個table

hbase是列式數據庫,rowkey是字典序的,設計時的規則同上。

每個列族是一個文件,將經常一起查詢的列放到同一個列族中,減少文件的尋址時間。

    1.     Redis,傳統數據庫,hbase,hive 每個之間的區別

redis:分佈式緩存,強調緩存,內存中數據

傳統數據庫:注重關係

hbase:列式數據庫,無法做關係數據庫的主外鍵,用於存儲海量數據,底層基於hdfs

hive:數據倉庫工具,底層是mapreduce。不是數據庫,不能用來做用戶的交互存儲

    1. shuffle 階段,你怎麼理解的

shuffle的過程說清楚,目的說清楚

    1. Mapreduce 的 map 數量 和 reduce 數量 怎麼確定 ,怎麼配置

map的數量有數據塊決定,reduce數量隨便配置。

    1. 唯一難住我的是他說實時計算,storm 如果碰上了複雜邏輯,需要算很長的時間,你怎麼去優化,怎麼保證實時性
    2. Hive 你們用的是外部表還是內部表,有沒有寫過UDF,hive 的版本

外部表和內部表的區別

    1. Hadoop 的版本

1.04、1.20都爲穩定版,是兩個常用的hadoop1版本。

    1. 實時流式計算 的結果內容有哪些,你們需要統計出來麼
    2.  

  1. 通過flume將不同系統的日誌收集到kafka中
  2. 通過storm實時的處理PV、UV、IP
  3. 通過kafka的consumer將日誌生產到hbase中。
  4. 通過離線的mapreduce或者hive,處理hbase中的數據

大體分爲3個部分:

  1. 離線hadoop技術分享(mapreduce、hive)
  2. nosql數據庫hbase分享
  3. 實時流計算分享

  1. 建表
  2. 分組(group by)統計wordcount

select word,count(1) from table1 group by word;

可以估計每個文件的大小爲50億×64=298G,遠遠大於內存限制的4G。所以不可能將其完全加載到內存中處理。考慮採取分而治之的方法。

  1. 將文件存儲到hdfs中,這樣每個文件爲64M或者是128M
  2. 分別對兩個文件的url進行去重、排序輸出,這樣能排除a文件中相同的url,b文件也一樣
  3. 對a、b兩個文件處理後的結果進行wordcount,並且在reduce中判斷單詞個數,個數爲2的時候輸出,這樣就找到了a、b文件中的相同url。
  4. 此計算步驟中的每一步加載到內存中的文件大小都不會超過64M,遠遠小於4G。

topk,強調使用treemap是爲了節省內存計算空間。

flume:日誌收集系統,主要用於系統日誌的收集

kafka:消息隊列,進行消息的緩存和系統的解耦

storm:實時計算框架,進行流式的計算。

簡單地說,就是一個變量和常量的關係。StringBuffer對象的內容可以修改;而String對象一旦產生後就不可以被修改,重新賦值其實是兩個對象。

StringBuilder:線程非安全的

StringBuffer:線程安全的

    當我們在字符串緩衝去被多個線程使用是,JVM不能保證StringBuilder的操作是安全的,雖然他的速度最快,但是可以保證StringBuffer是可以正確操作的。當然大多數情況下就是我們是在單線程下進行的操作,所以大多數情況下是建議用StringBuilder而不用StringBuffer的,就是速度的原因。

1 HashMap不是線程安全的

            hastmap是一個接口 map接口的子接口,是將鍵映射到值的對象,其中鍵和值都是對象,並且不能包含重複鍵,但可以包含重複值。HashMap允許null keynull value,而hashtable不允許。

 

2   HashTable是線程安全的一個Collection

 

HashMapHashtable的輕量級實現(非線程安全的實現),他們都完成了Map接口,主要區別在於HashMap允許空(null)鍵值(key,由於非線程安全,效率上可能高於Hashtable HashMap允許將null作爲一個entrykey或者value,而Hashtable不允許。 HashMapHashtablecontains方法去掉了,改成containsvaluecontainsKey。因爲contains方法容易讓人引起誤解。 Hashtable繼承自Dictionary類,而HashMapJava1.2引進的Map interface的一個實現。 最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多個線程訪問Hashtable時,不需要自己爲它的方法實現同步,而HashMap 就必須爲之提供外同步。 HashtableHashMap採用的hash/rehash算法都大概一樣,所以性能不會有很大的差

public static void main(String args[]) { HashTable h=new HashTable(); h.put("用戶1",new Integer(90)); h.put("用戶2",new Integer(50)); h.put("用戶3",new Integer(60)); h.put("用戶4",new Integer(70)); h.put("用戶5",new Integer(80)); Enumeration e=h.elements(); while(e.hasMoreElements()){ System.out.println(e.nextElement()); }

 

總結:

hashmap

線程不安全

允許有null的鍵和值

效率高一點、

方法不是Synchronize的要提供外同步

containsvaluecontainsKey方法

HashMap Java1.2 引進的Map interface 的一個實現

HashMapHashtable的輕量級實現

hashtable

線程安全

不允許有null的鍵和值

效率稍低、

方法是是Synchronize

contains方法方法

Hashtable 繼承於Dictionary

Hashtable HashMap 要舊

 

 Vector & ArrayList 
1  Vector的方法都是同步的(Synchronized),是線程安全的(thread-safe),而ArrayList的方法不是,由於線程的同步必然要影響性能,因此,ArrayList的性能比Vector好。 
2 VectorArrayList中的元素超過它的初始大小時,Vector會將它的容量翻倍,ArrayList只增加50%的大小,這樣,ArrayList就有利於節約內存空間。

 linkedlist & ArrayList 

ArrayList 採用的是數組形式來保存對象的,這種方式將對象放在連續的位置中,所以最大的缺點就是插入刪除時非常麻煩

LinkedList 採用的將對象存放在獨立的空間中,而且在每個空間中還保存下一個鏈接的索引  但是缺點就是查找非常麻煩 要叢第一個索引開始



Hashtable和HashMap類有三個重要的不同之處。第一個不同主要是歷史原因。Hashtable是基於陳舊的Dictionary類的,HashMap是Java 1.2引進的Map接口的一個實現。 



也許最重要的不同是Hashtable的方法是同步的,而HashMap的方法不是。這就意味着,雖然你可以不用採取任何特殊的行爲就可以在一個多線程的應用程序中用一個Hashtable,但你必須同樣地爲一個HashMap提供外同步。一個方便的方法就是利用Collections類的靜態的synchronizedMap()方法,它創建一個線程安全的Map對象,並把它作爲一個封裝的對象來返回。這個對象的方法可以讓你同步訪問潛在的HashMap。這麼做的結果就是當你不需要同步時,你不能切斷Hashtable中的同步(比如在一個單線程的應用程序中),而且同步增加了很多處理費用。 



第三點不同是,只有HashMap可以讓你將空值作爲一個表的條目的key或value。HashMap中只有一條記錄可以是一個空的key,但任意數量的條目可以是空的value。這就是說,如果在表中沒有發現搜索鍵,或者如果發現了搜索鍵,但它是一個空的值,那麼get()將返回null。如果有必要,用containKey()方法來區別這兩種情況。 



一些資料建議,當需要同步時,用Hashtable,反之用HashMap。但是,因爲在需要時,HashMap可以被同步,HashMap的功能比Hashtable的功能更多,而且它不是基於一個陳舊的類的,所以有人認爲,在各種情況下,HashMap都優先於Hashtable。 



關於Properties 

有時侯,你可能想用一個hashtable來映射key的字符串到value的字符串。DOS、Windows和Unix中的環境字符串就有一些例子,如key的字符串PATH被映射到value的字符串C:\WINDOWS;C:\WINDOWS\SYSTEM。Hashtables是表示這些的一個簡單的方法,但Java提供了另外一種方法。 



Java.util.Properties類是Hashtable的一個子類,設計用於String keys和values。Properties對象的用法同Hashtable的用法相象,但是類增加了兩個節省時間的方法,你應該知道。 



Store()方法把一個Properties對象的內容以一種可讀的形式保存到一個文件中。Load()方法正好相反,用來讀取文件,並設定Properties對象來包含keys和values。 



注意,因爲Properties擴展了Hashtable,你可以用超類的put()方法來添加不是String對象的keys和values。這是不可取的。另外,如果你將store()用於一個不包含String對象的Properties對象,store()將失敗。作爲put()和get()的替代,你應該用setProperty()和getProperty(),它們用String參數。

 

在java中可有兩種方式實現多線程,一種是繼承Thread類,一種是實現Runnable接口;Thread類是在java.lang包中定義的。一個類只要繼承了Thread類同時覆寫了本類中的run()方法就可以實現多線程操作了,但是一個類只能繼承一個父類,這是此方法的侷限。

AD

在java中可有兩種方式實現多線程,一種是繼承Thread類,一種是實現Runnable接口;Thread類是在java.lang包中定義的。一個類只要繼承了Thread類同時覆寫了本類中的run()方法就可以實現多線程操作了,但是一個類只能繼承一個父類,這是此方法的侷限。

下面看例子:

  1. package org.thread.demo;  
  2. class MyThread extends Thread{  
  3. private String name;  
  4. public MyThread(String name) {  
  5. super();  
  6. this.name = name;  
  7. }  
  8. public void run(){  
  9. for(int i=0;i<10;i++){  
  10. System.out.println("線程開始:"+this.name+",i="+i);  
  11. }  
  12. }  
  13. }  
  14. package org.thread.demo;  
  15. public class ThreadDemo01 {  
  16. public static void main(String[] args) {  
  17. MyThread mt1=new MyThread("線程a");  
  18. MyThread mt2=new MyThread("線程b");  
  19. mt1.run();  
  20. mt2.run();  
  21. }  

但是,此時結果很有規律,先第一個對象執行,然後第二個對象執行,並沒有相互運行。在JDK的文檔中可以發現,一旦調用start()方法,則會通過JVM找到run()方法。下面啓動start()方法啓動線程:

  1. package org.thread.demo;  
  2. public class ThreadDemo01 {  
  3. public static void main(String[] args) {  
  4. MyThread mt1=new MyThread("線程a");  
  5. MyThread mt2=new MyThread("線程b");  
  6. mt1.start();  
  7. mt2.start();  
  8. }  
  9. }; 

這樣程序可以正常完成交互式運行。那麼爲啥非要使用start();方法啓動多線程呢?

在JDK的安裝路徑下,src.zip是全部的java源程序,通過此代碼找到Thread中的start()方法的定義,可以發現此方法中使用了private native void start0();其中native關鍵字表示可以調用操作系統的底層函數,那麼這樣的技術成爲JNI技術(java Native Interface)

Runnable接口

在實際開發中一個多線程的操作很少使用Thread類,而是通過Runnable接口完成。

  1. public interface Runnable{  
  2. public void run();  

例子:

  1. package org.runnable.demo;  
  2. class MyThread implements Runnable{  
  3. private String name;  
  4. public MyThread(String name) {  
  5. this.name = name;  
  6. }
  7. public void run(){  
  8. for(int i=0;i<100;i++){  
  9. System.out.println("線程開始:"+this.name+",i="+i);  
  10. }  
  11. }  
  12. }; 

但是在使用Runnable定義的子類中沒有start()方法,只有Thread類中才有。此時觀察Thread類,有一個構造方法:public Thread(Runnable targer)此構造方法接受Runnable的子類實例,也就是說可以通過Thread類來啓動Runnable實現的多線程。(start()可以協調系統的資源):

  1. package org.runnable.demo;  
  2. import org.runnable.demo.MyThread;  
  3. public class ThreadDemo01 {  
  4. public static void main(String[] args) {  
  5. MyThread mt1=new MyThread("線程a");  
  6. MyThread mt2=new MyThread("線程b");  
  7. new Thread(mt1).start();  
  8. new Thread(mt2).start();  
  9. }  

兩種實現方式的區別和聯繫:

在程序開發中只要是多線程肯定永遠以實現Runnable接口爲主,因爲實現Runnable接口相比繼承Thread類有如下好處:

  • 避免點繼承的侷限,一個類可以繼承多個接口。
  • 適合於資源的共享

以賣票程序爲例,通過Thread類完成:

  1. package org.demo.dff;  
  2. class MyThread extends Thread{  
  3. private int ticket=10;  
  4. public void run(){  
  5. for(int i=0;i<20;i++){  
  6. if(this.ticket>0){  
  7. System.out.println("賣票:ticket"+this.ticket--);  
  8. }  
  9. }  
  10. }  
  11. }; 

下面通過三個線程對象,同時賣票:

  1. package org.demo.dff;  
  2. public class ThreadTicket {  
  3. public static void main(String[] args) {  
  4. MyThread mt1=new MyThread();  
  5. MyThread mt2=new MyThread();  
  6. MyThread mt3=new MyThread();  
  7. mt1.start();//每個線程都各賣了10張,共賣了30張票  
  8. mt2.start();//但實際只有10張票,每個線程都賣自己的票  
  9. mt3.start();//沒有達到資源共享  
  10. }  

如果用Runnable就可以實現資源共享,下面看例子:

  1. package org.demo.runnable;  
  2. class MyThread implements Runnable{  
  3. private int ticket=10;  
  4. public void run(){  
  5. for(int i=0;i<20;i++){  
  6. if(this.ticket>0){  
  7. System.out.println("賣票:ticket"+this.ticket--);  
  8. }  
  9. }  
  10. }  
  11. }  
  12. package org.demo.runnable;  
  13. public class RunnableTicket {  
  14. public static void main(String[] args) {  
  15. MyThread mt=new MyThread();  
  16. new Thread(mt).start();//同一個mt,但是在Thread中就不可以,如果用同一  
  17. new Thread(mt).start();//個實例化對象mt,就會出現異常  
  18. new Thread(mt).start();  
  19. }  
  20. }; 

雖然現在程序中有三個線程,但是一共賣了10張票,也就是說使用Runnable實現多線程可以達到資源共享目的。

    1.  

hdfs在存儲的時候不會將數據進行壓縮,如果想進行壓縮,我們可以在向hdfs上傳數據的時候進行壓縮。

    1. 採用壓縮流

//壓縮文件

    public static void compress(String codecClassName) throws Exception{

        Class<?> codecClass = Class.forName(codecClassName);

        Configuration conf = new Configuration();

        FileSystem fs = FileSystem.get(conf);

        CompressionCodec codec = (CompressionCodec)ReflectionUtils.newInstance(codecClass, conf);

        //指定壓縮文件路徑

        FSDataOutputStream outputStream = fs.create(new Path("/user/hadoop/text.gz"));

        //指定要被壓縮的文件路徑

        FSDataInputStream in = fs.open(new Path("/user/hadoop/aa.txt"));

        //創建壓縮輸出流

        CompressionOutputStream out = codec.createOutputStream(outputStream); 

        IOUtils.copyBytes(in, out, conf);

        IOUtils.closeStream(in);

        IOUtils.closeStream(out);

    }

    1. 採用序列化文件

public void testSeqWrite() throws Exception {

 

                     Configuration conf = new Configuration();// 創建配置信息

                     conf.set("fs.default.name", "hdfs://master:9000");// hdfs默認路徑

                     conf.set("hadoop.job.ugi", "hadoop,hadoop");// 用戶和組信息

                     String uriin = "hdfs://master:9000/ceshi2/";// 文件路徑

                     FileSystem fs = FileSystem.get(URI.create(uriin), conf);// 創建filesystem

                     Path path = new Path("hdfs://master:9000/ceshi3/test.seq");// 文件名

                     IntWritable k = new IntWritable();// key,相當於int

                     Text v = new Text();// value,相當於String

                     SequenceFile.Writer w = SequenceFile.createWriter(fs, conf, path,

                                          k.getClass(), v.getClass());// 創建writer

                     for (int i = 1; i < 100; i++) {// 循環添加

                                k.set(i);

                                v.set("abcd");

                                w.append(k, v);

                     }

                     w.close();

                     IOUtils.closeStream(w);// 關閉的時候flush

                     fs.close();

           }

hbase爲列存數據庫,本身存在壓縮機制,所以無需設計。

    1. 在庫表設計的時候,儘量考慮rowkey和columnfamily的特性
    2. 進行hbase集羣的調優:見hbase調優

hbase的filter是通過scan設置的,所以是基於scan的查詢結果進行過濾。

  1. 在進行訂單開發的時候,我們使用rowkeyfilter過濾出某個用戶的所有訂單
  2. 在進行雲筆記開發時,我們使用rowkey過濾器進行redis數據的恢復。

使用rowkey過濾器實現

Hive提供了三個虛擬列:

INPUT__FILE__NAME

BLOCK__OFFSET__INSIDE__FILE

ROW__OFFSET__INSIDE__BLOCK

但ROW__OFFSET__INSIDE__BLOCK默認是不可用的,需要設置hive.exec.rowoffset爲true纔可以。可以用來排查有問題的輸入數據。

INPUT__FILE__NAME, mapper任務的輸出文件名。

BLOCK__OFFSET__INSIDE__FILE, 當前全局文件的偏移量。對於塊壓縮文件,就是當前塊的文件偏移量,即當前塊的第一個字節在文件中的偏移量。

hive> SELECT INPUT__FILE__NAME, BLOCK__OFFSET__INSIDE__FILE, line

 

> FROM hive_text WHERE line LIKE '%hive%' LIMIT 2;

 

har://file/user/hive/warehouse/hive_text/folder=docs/

 

data.har/user/hive/warehouse/hive_text/folder=docs/README.txt  2243

 

har://file/user/hive/warehouse/hive_text/folder=docs/

 

data.har/user/hive/warehouse/hive_text/folder=docs/README.txt  3646

    1. 將小文件打成har文件存儲
    2. 將小文件序列化到hdfs中

寫個mapreduce鏈  用依賴關係,一共三個mapreduce,第一個處理第一個文件,第二個處理第二個文件,第三個處理前兩個的輸出結果,第一個mapreduce將文件去重,第二個mapreduce也將文件去重,第三個做wordcount,wordcount爲1的結果就是不同的

  1. 共同朋友

思路:例如A,他的朋友是B\C\D\E\F\,那麼BC的共同朋友就是A。所以將BC作爲key,將A作爲value,在map端輸出即可!其他的朋友循環處理。

import java.io.IOException;

2.

import java.util.Set;

3.

import java.util.StringTokenizer;

4.

import java.util.TreeSet;

5.

 

6.

import org.apache.hadoop.conf.Configuration;

7.

import org.apache.hadoop.fs.Path;

8.

import org.apache.hadoop.io.Text;

9.

import org.apache.hadoop.mapreduce.Job;

10. import org.apache.hadoop.mapreduce.Mapper;

11. import org.apache.hadoop.mapreduce.Reducer;

12. import org.apache.hadoop.mapreduce.Mapper.Context;

13. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;

14. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

15. import org.apache.hadoop.util.GenericOptionsParser;

16. 

17. public class FindFriend {

www.aboutyun.com

18.         

19.           public static class ChangeMapper extends Mapper<Object, Text, Text,

Text>{                      

20.                    @Override

21.                    public void map(Object key, Text value, Context context) throws

IOException, InterruptedException {

22.                              StringTokenizer itr = new StringTokenizer(value.toString());

23.                                  Text owner = new Text();

24.                                  Set<String> set = new TreeSet<String>();

25.                              owner.set(itr.nextToken());

26.                              while (itr.hasMoreTokens()) {

27.                                      set.add(itr.nextToken());

28.                              }             

29.                              String[] friends = new String[set.size()];

30.                              friends = set.toArray(friends);

31.                              

32.                              for(int i=0;i<friends.length;i++){

33.                                      for(int j=i+1;j<friends.length;j++){

34.                                              String outputkey = friends[i]+friends[j];

35.                                              context.write(new Text(outputkey),owner);

36.                                      }                                      

37.                              }

38.                    }

39.           }

40.           

41.           public static class FindReducer extends Reducer<Text,Text,Text,Text>

{                          

42.                         public void reduce(Text key, Iterable<Text> values, 

43.                                         Context context) throws IOException,

InterruptedException {

44.                                   String  commonfriends =""; 

www.aboutyun.com

45.                               for (Text val : values) {

46.                                   if(commonfriends == ""){

47.                                           commonfriends = val.toString();

48.                                   }else{

49.                                           commonfriends =

commonfriends+":"+val.toString();

50.                                   }

51.                                }

52.                               context.write(key, new

Text(commonfriends));                                 

53.                         }                          

54.           }

55.           

56. 

57.         public static void main(String[] args) throws IOException,

58.         InterruptedException, ClassNotFoundException {

59.                 

60.             Configuration conf = new Configuration();

61.             String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();

62.             if (otherArgs.length < 2) {

63.               System.err.println("args error");

64.               System.exit(2);

65.             }

66.             Job job = new Job(conf, "word count");

67.             job.setJarByClass(FindFriend.class);

68.             job.setMapperClass(ChangeMapper.class);

69.             job.setCombinerClass(FindReducer.class);

70.             job.setReducerClass(FindReducer.class);

71.             job.setOutputKeyClass(Text.class);

72.             job.setOutputValueClass(Text.class);

73.             for (int i = 0; i < otherArgs.length - 1; ++i) {

www.aboutyun.com

74.               FileInputFormat.addInputPath(job, new Path(otherArgs[i]));

75.             }

76.             FileOutputFormat.setOutputPath(job,

77.               new Path(otherArgs[otherArgs.length - 1]));

78.             System.exit(job.waitForCompletion(true) ? 0 : 1);

79.                 

80.         }

81. 

82. }

結果:

1. AB      E:C:D

2. AC      E:B

3. AD      B:E

4. AE      C:B:D

5. BC      A:E

6. BD      A:E

7. BE      C:D:A

8. BF      A

9. CD      E:A:B

10. CE      A:B

11. CF      A

12. DE      B:A

13. DF      A

14. EF      A

  1. 基站逗留時間

需求:

期望:

思路:

將數據導入hive表中,查詢時,用電話號碼和時間排序即可!

  1. 腳本替換

腳本:隨意命名爲aaa.sh

#!/bin/bash

ls $1 | while read line

do

sed -i 's,\$HADOOP_HOME\$,\/home\/aa,g' $1$line

echo $1$line

done

腳本執行命令:替換/home/hadoop/test/下的所有文件

./aaa.sh /home/hadoop/test/

  1. 一鍵執行

腳本:

vi runRemoteCmd.sh

#!/bin/bash

$1

ssh -q hadoop@slave1 "$1"

ssh -q hadoop@slave2 "$1"

執行命令

./runRemoteCmd.sh "ls -l"

 

  1. 大數據面試彙總
  1. 講解一下MapReduce 的一些基本流程

任務提交流程,任務運行流程

  1. 你們數據庫怎麼導入hive 的,有沒有出現問題

使用sqoop導入,我們公司的數據庫中設計了text字段,導致導入的時候出現了緩存不夠的情況(見雲筆記),開始解決起來感覺很棘手,後來查看了sqoop的文檔,加上了limit屬性,解決了。

  1. 公司技術選型可能利用storm 進行實時計算,講解一下storm

從storm的應用,代碼書寫,運行機制講

  1. 問你java 集合類的數據結構,比如hashmap

看java面試寶典

  1. 問你知不知道concurrent 包下的東西,例如concurrenthashmap

看java面試寶典

  1. 公司最近主要在自然語言學習去開發,有沒有接觸過

沒有用過

  1. 面試問題:
  1. 從前到後從你教育背景(學過哪些課)到各個項目你負責的模塊,問的很細(本以爲他是物理學博士,但是所有的技術都懂)

 

  1. hadoop 的 namenode 宕機,怎麼解決

先分析宕機後的損失,宕機後直接導致client無法訪問,內存中的元數據丟失,但是硬盤中的元數據應該還存在,如果只是節點掛了,重啓即可,如果是機器掛了,重啓機器後看節點是否能重啓,不能重啓就要找到原因修復了。但是最終的解決方案應該是在設計集羣的初期就考慮到這個問題,做namenode的HA。

 

  1. 一個datanode 宕機,怎麼一個流程恢復

Datanode宕機了後,如果是短暫的宕機,可以實現寫好腳本監控,將它啓動起來。如果是長時間宕機了,那麼datanode上的數據應該已經被備份到其他機器了,那這臺datanode就是一臺新的datanode了,刪除他的所有數據文件和狀態文件,重新啓動。

 

  1. Hbase 的特性,以及你怎麼去設計 rowkey 和 columnFamily ,怎麼去建一個table

因爲hbase是列式數據庫,列非表schema的一部分,所以在設計初期只需要考慮rowkey 和 columnFamily即可,rowkey有位置相關性,所以如果數據是練習查詢的,最好對同類數據加一個前綴,而每個columnFamily實際上在底層是一個文件,那麼文件越小,查詢越快,所以講經常一起查詢的列設計到一個列簇,但是列簇不宜過多。

 

  1. Redis,傳統數據庫,hbase,hive 每個之間的區別(問的非常細)

Redis是緩存,圍繞着內存和緩存說

Hbase是列式數據庫,存在hdfs上,圍繞着數據量來說

Hive是數據倉庫,是用來分析數據的,不是增刪改查數據的。

 

  1. 公司之後傾向用spark 開發,你會麼(就用java代碼去寫)

會,spark使用scala開發的,在scala中可以隨意使用jdk的類庫,可以用java開發,但是最好用原生的scala開發,兼容性好,scala更靈活。

 

  1. 面試問題:
  1. 筆試: java基礎(基本全忘,做的很爛,複習大數據連單例都忘了怎麼寫)

複習java面試寶典

 

  1. 開始介紹項目,直接用大數據項目介紹,項目經理也懂大數據

 

  1. Mapreduce 一些流程,經過哪些步驟

Map—combiner—partition—sort—copy—sort—grouping—reduce

 

  1. 說下對hadoop 的一些理解,包括哪些組件

詳談hadoop的應用,包括的組件分爲三類,分別說明hdfs,yarn,mapreduce

 

  1. 詳細講解下你流式實時計算的項目部署以及收集的結果情況

講解storm集羣的部署方案,項目的大小,使用的worker數,數據收集在hbase或者hdfs,好處是什麼

 

  1. 你的數據庫是不是很大麼,有沒有分表,分區,你是怎麼實現的

數據庫的分表在設計初期是按照月份進行拆分的,不同的月份查詢不同的表。分區沒弄過。

 

  1. 開始問java的一些東西(從各種框架原理到各種複雜SQL)

 

  1. 多線程,併發,垃圾回收機制,數據結構(問這些,基本覺得看你是不是高級程序員了)

多線程要知道操作方式,線程安全的鎖,並且要知道lock鎖

垃圾回收機制需要詳細瞭解(見雲筆記),主要從內存劃分,垃圾回收主要的工作區域,垃圾回收器的種類,各有什麼優缺點,用在哪裏合適。

數據結構基本的要知道,複雜的參考相關的書籍。

 

  1. 面試問題:
  1. BI小組的3個年輕學生一起技術面試(一個是南開博士

 

  1. 數據量多少,集羣規模多大,型號

一般中型的電商或者互聯網企業,日誌量每天在200-500M左右,集羣規模在30-50臺左右,機器一般爲dell的2000左右的服務器,型號不定

大型的互聯網公司據網上資料顯示,日誌量在GP-PB不等,集羣規模在500-4000不等,甚至更多,機器型號不確定。

 

  1. 項目,mapreduce

介紹整個mapreduce項目流程,數據採集—數據聚合—數據分析—數據展示等

  1. 實時流式計算框架,幾個人,多長時間,細節問題,包括講flume ,kafka ,storm 的各個的組件組成,你負責那一塊,如果需要你搭建你可以完成麼?

 

 

  1. 你覺得spark 可以完全替代hadoop 麼?

 

  1. 面試問題:
  1. 一些傳統的hadoop 問題,mapreduce 他就問shuffle 階段,你怎麼理解的

Shuffle意義在於將不同map處理後的數據進行合理分配,讓reduce處理,從而產生了排序、分區。

 

  1. Mapreduce 的 map 數量 和 reduce 數量 怎麼確定 ,怎麼配置

Map無法配置,reduce隨便配置

 

  1. 唯一難住我的是他說實時計算,storm 如果碰上了複雜邏輯,需要算很長的時間,你怎麼去優化

拆分複雜的業務到多個bolt中,這樣可以利用bolt的tree將速度提升

 

  1. Hive 你們用的是外部表還是內部表,有沒有寫過UDF(當然吹自己寫過了),hive 的版本

外部表,udf,udaf等,hive版本爲1.0

 

  1. Hadoop 的版本

如果是1.0版本就說1.2,如果是2.0版本,就說2.6或者2.7

1.2爲官方穩定版本,2.7爲官方穩定版本。

Apache Hadoop 2.7.1於美國時間2015年07月06日正式發佈,本版本屬於穩定版本,是自Hadoop 2.6.0以來又一個穩定版,同時也是Hadoop 2.7.x版本線的第一個穩定版本,也是 2.7版本線的維護版本,變化不大,主要是修復了一些比較嚴重的Bug

 

  1. 實時流式計算的結果內容有哪些,你們需要統計出來麼(我就說highchart展示)

簡單介紹日誌監控、風控等結果內容,統計出來顯示在報表或者郵件中。

 

  1. 開始問java相關,包括luecne,solr(倒排索引的原理),框架呀,redis呀

 

  1. 京東商城 - 大數據

(1)Java篇

1、JVM,GC(算法,新生代,老年代),JVM結構

 

2、hashcode,hashMap,list,hashSet,equals(結構原理),A extends  B(類的加載順序)

1.父類靜態代碼塊;

2.子類靜態代碼塊;

3.父類非靜態代碼塊;

4.父類構造函數;

5.子類非靜態代碼塊;

6.子類構造函數;

3、多線程,主線程,次線程,喚醒,睡眠

4、常見算法:冒泡算法,排序算法,二分查找,時間複雜度

(2)Flume篇

1、數據怎麼採集到Kafka,實現方式

使用官方提供的flumeKafka插件,插件的實現方式是自定義了flume的sink,將數據從channle中取出,通過kafka的producer寫入到kafka中,可以自定義分區等。

 

2、flume管道內存,flume宕機了數據丟失怎麼解決

1、Flume的channel分爲很多種,可以將數據寫入到文件

       2、防止非首個agent宕機的方法數可以做集羣或者主備

 

3、flume配置方式,flume集羣(問的很詳細)

Flume的配置圍繞着source、channel、sink敘述,flume的集羣是做在agent上的,而非機器上。

 

4、flume不採集Nginx日誌,通過Logger4j採集日誌,優缺點是什麼?

優點:Nginx的日誌格式是固定的,但是缺少sessionid,通過logger4j採集的日誌是帶有sessionid的,而session可以通過redis共享,保證了集羣日誌中的同一session落到不同的tomcat時,sessionId還是一樣的,而且logger4j的方式比較穩定,不會宕機。

缺點:不夠靈活,logger4j的方式和項目結合過於緊密,而flume的方式比較靈活,拔插式比較好,不會影響項目性能。

 

5、flume和kafka採集日誌區別,採集日誌時中間停了,怎麼記錄之前的日誌。

Flume採集日誌是通過流的方式直接將日誌收集到存儲層,而kafka試講日誌緩存在kafka集羣,待後期可以採集到存儲層。

Flume採集中間停了,可以採用文件的方式記錄之前的日誌,而kafka是採用offset的方式記錄之前的日誌。

 

(3)Kafka篇

1、容錯機制

分區備份,存在主備partition

 

2、同一topic不同partition分區

????

3、kafka數據流向

Producer à leader partition à follower partition(半數以上) àconsumer

4、kafka+spark-streaming結合丟數據怎麼解決?

spark streaming1.2開始提供了數據的零丟失,想享受這個特性,需要滿足如下條件:

  1. 數據輸入需要可靠的sources和可靠的receivers
  2. 應用metadata必須通過應用driver checkpoint
  3. WALwrite ahead log
    1. 可靠的sourcesreceivers

spark streaming可以通過多種方式作爲數據sources(包括kafka),輸入數據通過receivers接收,通過replication存儲於spark中(爲了faultolerance,默認複製到兩個spark executors),如果數據複製完成,receivers可以知道(例如kafka中更新offsetszookeeper中)。這樣當receivers在接收數據過程中crash掉,不會有數據丟失,receivers沒有複製的數據,當receiver恢復後重新接收。

    1. metadata checkpoint

可靠的sourcesreceivers,可以使數據在receivers失敗後恢復,然而在driver失敗後恢復是比較複雜的,一種方法是通過checkpoint metadataHDFS或者S3metadata包括:

  • configuration
  • code
  • 一些排隊等待處理但沒有完成的RDD(僅僅是metadata,而不是data)

這樣當driver失敗時,可以通過metadata checkpoint,重構應用程序並知道執行到那個地方。

    1. 數據可能丟失的場景

可靠的sourcesreceivers,以及metadata checkpoint也不可以保證數據的不丟失,例如:

  • 兩個executor得到計算數據,並保存在他們的內存中
  • receivers知道數據已經輸入
  • executors開始計算數據
  • driver突然失敗
  • driver失敗,那麼executors都會被kill掉
  • 因爲executor被kill掉,那麼他們內存中得數據都會丟失,但是這些數據不再被處理
  • executor中的數據不可恢復
    1. WAL

爲了避免上面情景的出現,spark streaming 1.2引入了WAL。所有接收的數據通過receivers寫入HDFS或者S3checkpoint目錄,這樣當driver失敗後,executor中數據丟失後,可以通過checkpoint恢復。

    1. At-Least-Once

儘管WAL可以保證數據零丟失,但是不能保證exactly-once,例如下面場景:

  • Receivers接收完數據並保存到HDFSS3
  • 在更新offset前,receivers失敗了
  • Spark Streaming以爲數據接收成功,但是Kafka以爲數據沒有接收成功,因爲offset沒有更新到zookeeper
  • 隨後receiver恢復了
  • WAL可以讀取的數據重新消費一次,因爲使用的kafka High-Level消費API,從zookeeper中保存的offsets開始消費
    1. WAL的缺點

通過上面描述,WAL有兩個缺點:

  • 降低了receivers的性能,因爲數據還要存儲到HDFS等分佈式文件系統
  • 對於一些resources,可能存在重複的數據,比如Kafka,在Kafka中存在一份數據,在Spark Streaming也存在一份(以WAL的形式存儲在hadoop API兼容的文件系統中)
    1. Kafka direct API

爲了WAL的性能損失和exactly-oncespark streaming1.3中使用Kafka direct API。非常巧妙,Spark driver計算下個batchoffsets,指導executor消費對應的topicspartitions。消費Kafka消息,就像消費文件系統文件一樣。

  1. 不再需要kafka receiversexecutor直接通過Kafka API消費數據
  2. WAL不再需要,如果從失敗恢復,可以重新消費
  3. exactly-once得到了保證,不會再從WAL中重複讀取數據
    1. 總結

主要說的是spark streaming通過各種方式來保證數據不丟失,並保證exactly-once,每個版本都是spark streaming越來越穩定,越來越向生產環境使用發展。

 

 

5、kafka中存儲目錄data/dir.....topic1和topic2怎麼存儲的,存儲結構,data.....目錄下有多少個分區,每個分區的存儲格式是什麼樣的?

       1、topic是按照“主題名-分區”存儲的

       2、分區個數由配置文件決定

       3、每個分區下最重要的兩個文件是0000000000.log和000000.index,0000000.log以默認1G大小回滾。

 

(4)Hive篇

 

1、hive partition分區

分區表,動態分區

 

2、insert into 和 override write區別?

insert into:將某一張表中的數據寫到另一張表中

override write:覆蓋之前的內容。

 

3、假如一個分區的數據主部錯誤怎麼通過hivesql刪除hdfs

alter table ptable drop partition (daytime='20140911',city='bj');

元數據,數據文件都刪除,但目錄daytime= 20140911還在

 

(5)Storm篇         

 1、開發流程,容錯機制

開發流程:

    1. 寫主類(設計spout和bolt的分發機制)
    2. 寫spout收集數據
    3. 寫bolt處理數據,根據數據量和業務的複雜程度,設計並行度。

容錯機制:採用ack和fail進行容錯,失敗的數據重新發送。

2、storm和spark-streaming:爲什麼用storm不同spark-streaming

 

3、mr和spark區別,怎麼理解spark-rdd

Mr是文件方式的分佈式計算框架,是將中間結果和最終結果記錄在文件中,map和reduce的數據分發也是在文件中。

spark是內存迭代式的計算框架,計算的中間結果可以緩存內存,也可以緩存硬盤,但是不是每一步計算都需要緩存的。

Spark-rdd是一個數據的分區記錄集合………………

 

4、sqoop命令

sqoop import --connect jdbc:mysql://192.168.56.204:3306/sqoop --username hive --password hive --table jobinfo --target-dir /sqoop/test7 --inline-lob-limit 16777216 --fields-terminated-by '\t' -m 2

sqoop create-hive-table --connect jdbc:mysql://192.168.56.204:3306/sqoop --table jobinfo --username hive --password hive --hive-table sqtest --fields-terminated-by "\t" --lines-terminated-by "\n";

 

(6)Redis篇

1、基本操作,存儲格式

 

(7)Mysql篇

1、mysql集羣的分佈式事務

京東自主開發分佈式MYSQL集羣系統

 

2、mysql性能優化(數據方面)

數據的分表、分庫、分區

 

(6)Hadoop篇

1、hadoop HA  兩個namenode和zk之間的通信,zk的選舉機制?

HA是通過先後獲取zk的鎖決定誰是主

Zk的選舉機制,涉及到全新機羣的選主和數據恢復的選主

 

2、mr運行機制

3、yarn流程

 

1)       用戶向YARN 中提交應用程序, 其中包括ApplicationMaster 程序、啓動ApplicationMaster 的命令、用戶程序等。

2)       ResourceManager 爲該應用程序分配第一個Container, 並與對應的NodeManager 通信,要求它在這個Container 中啓動應用程序的ApplicationMaster。

3)       ApplicationMaster 首先向ResourceManager 註冊, 這樣用戶可以直接通過ResourceManage 查看應用程序的運行狀態,然後它將爲各個任務申請資源,並監控它的運行狀態,直到運行結束,即重複步驟4~7。

4)       ApplicationMaster 採用輪詢的方式通過RPC 協議向ResourceManager 申請和領取資源。

5)       一旦ApplicationMaster 申請到資源後,便與對應的NodeManager 通信,要求它啓動任務。

6)       NodeManager 爲任務設置好運行環境(包括環境變量、JAR 包、二進制程序等)後,將任務啓動命令寫到一個腳本中,並通過運行該腳本啓動任務。

7)       各個任務通過某個RPC 協議向ApplicationMaster 彙報自己的狀態和進度,以讓ApplicationMaster 隨時掌握各個任務的運行狀態,從而可以在任務失敗時重新啓動任務。在應用程序運行過程中,用戶可隨時通過RPC 向ApplicationMaster 查詢應用程序的當前運行狀態。

8)       應用程序運行完成後,ApplicationMaster 向ResourceManager 註銷並關閉自己。

 

(7)Hbase

1、涉及到概念,文檔

 

(8)Spark篇

1、spark原理  

Spark應用轉換流程

    1. spark應用提交後,經歷了一系列的轉換,最後成爲task在每個節點上執行
    2. RDD的Action算子觸發Job的提交,生成RDD DAG
    3. 由DAGScheduler將RDD DAG轉化爲Stage DAG,每個Stage中產生相應的Task集合
    4. TaskScheduler將任務分發到Executor執行
    5. 每個任務對應相應的一個數據塊,只用用戶定義的函數處理數據塊

 

Driver運行在Worker

 

    通過org.apache.spark.deploy.Client類執行作業,作業運行命令如下:

作業執行流程描述:

1、客戶端提交作業給Master

2、Master讓一個Worker啓動Driver,即SchedulerBackend。Worker創建一個DriverRunner線程,DriverRunner啓動SchedulerBackend進程。

3、另外Master還會讓其餘Worker啓動Exeuctor,即ExecutorBackend。Worker創建一個ExecutorRunner線程,ExecutorRunner會啓動ExecutorBackend進程。

4、ExecutorBackend啓動後會向Driver的SchedulerBackend註冊。SchedulerBackend進程中包含DAGScheduler,它會根據用戶程序,生成執行計劃,並調度執行。對於每個stage的task,都會被存放到TaskScheduler中,ExecutorBackend向SchedulerBackend彙報的時候把TaskScheduler中的task調度到ExecutorBackend執行。

5、所有stage都完成後作業結束。

 

 

Driver運行在客戶端

 

  

 

作業執行流程描述:

1、客戶端啓動後直接運行用戶程序,啓動Driver相關的工作:DAGScheduler和BlockManagerMaster等。

2、客戶端的Driver向Master註冊。

3、Master還會讓Worker啓動Exeuctor。Worker創建一個ExecutorRunner線程,ExecutorRunner會啓動ExecutorBackend進程。

4、ExecutorBackend啓動後會向Driver的SchedulerBackend註冊。Driver的DAGScheduler解析作業並生成相應的Stage,每個Stage包含的Task通過TaskScheduler分配給Executor執行。

5、所有stage都完成後作業結束。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章