提升Hive操作Amazon S3讀寫數據的性能
通常通過Amazon S3讀取和寫入數據的速度也要慢於使用HDFS,即使Amazon S3存儲桶與基於Amazon EC2基礎架構上運行的Hadoop集群,原因如下:
1、在Amazon S3上,重命名是非常昂貴的複製操作。 在提交階段,重命名表面的性能下降,其中包括:
- MapReduce FileOutputCommitter
- DistCp在複製操作後重命名
- Hadoop FileSystem shell輸入操作,如果垃圾箱已啟用,則輸入-rm
2、寫操作只能從close()操作完成後才開始,操作可能需要很長時間並且其中的某些過程可能會超時;
3、性能問題也可能由於HTTP請求的大小而發生。
Hive操作S3許可權的優化
參數推薦值參數說明
hive.warehouse.subdir.inherit.permsfalse由於S3沒有文件許可權的概念,請設置hive.warehouse.subdir.inherit.perms = false以減少文件許可權檢查的次數hive.metastore.pre.event.listeners(空)由於S3沒有目錄許可權的概念,請設置hive.metastore.pre.event.listeners =(設置為空值)以減少S3中目錄許可權檢查的次數 以上參數設置在hive-site.xml中。
Hive提高讀取ORC格式Job的優化
參數推薦值參數說明hive.orc.compute.splits.num.threads默認值為10如果使用ORC格式並且希望改進拆分計算時間,則可以增加hive.orc.compute.splits.num.threads(默認值為10)。此參數控制計算拆分中涉及的並行線程的數量。請注意,對於Parquet,它仍然是單線程的,所以拆分計算可能需要更長的Parquet和S3hive.orc.splits.include.file.footertrue如果將ORC格式與ETL文件拆分策略一起使用,則可以設置hive.orc.splits.include.file.footer = true以搭載拆分有效內容中的文件頁腳信息 可以使用Hive CLI中的--hiveconf選項或使用Beeline中的set命令來設置這些參數。
加速ETL作業
參數推薦值參數說明hive.stats.fetch.partition.statsfalsehive.stats.fetch.partition.stats如果沒有可用的統計信息或hive.stats.fetch.partition.stats = false,則查詢啟動可能會稍慢。在這種情況下,Hive最終會為每個要訪問的文件查看文件大小,調整hive.metastore.fshandler.threads有助於減少Metastore操作所需的總時間fs.trash.interval0由於操作涉及將文件移動到垃圾箱(副本+刪除),因此在S3中,drop table可能會很慢,因此可以將fs.trash.interval = 0設置為完全跳過垃圾桶可以使用Hive CLI中的--hiveconf選項或使用Beeline中的set命令來設置這些參數。
在Hive中加速插入參數
推 薦值參數說明hive.mv.files.thread默認值為15插入數據時,Hive將數據從臨時文件夾移動到最終位置。這個移動操作實際上是一個複製+刪除操作,這在Amazon S3中很貴;向S3寫入的數據越多,操作的成本就越高。為了加速該過程,您可以調整hive.mv.files.thread(默認值為15),具體取決於數據集的大小。提高容器分配性能
參數推薦值參數說明yarn.scheduler.capacity.node-locality-delay0由於AWS不具備機架位置的概念,設置yarn.scheduler.capacity.node-locality-delay = 0可以啟用更快的容器,更多信息,請參閱Capacity Scheduler相關文檔優化HTTP GET請求(註:這些優化參數,當前還初於實驗性階段,將來其行為可能會改變)
實驗性的fadvice策略介紹
S3A文件系統客戶端支持輸入策略的概念,類似於POSIX fadvise()API調用的概念。 這會調整S3A客戶端的行為以優化各種用例的HTTP GET請求。 要優化HTTP GET請求,可以使用S3A實驗輸入策略fs.s3a.experimental.input.fadvise:
策略描述sequential (default) 整個文檔在一個HTTP請求中被請求,被順序讀取,通過跳過中間數據支持在預讀範圍內的前向搜索,這會讓讀取操作吞吐量達到最大,但會帶來非常昂貴的後向搜索。normal當前的行為同sequential是一樣的random針對隨機IO進行了優化,特別是針對Hadoop的`PositionedReadable`操作 - 使用seek(offset);read(byte_buffer)`操作同樣也有提升。
與順序讀取的不同,HTTP請求讀取不是整個文件,而是通過`read`操作設置所需要讀取的數據長度的範圍 - 如果有必要,可能通過對通過setReadahead()的值的範圍進行四捨五入的操作。
通過降低關閉現有HTTP請求的成本,這對於文件IO通過一系列`PositionedReadable.read()`和`PositionedReadable.readFully()`調用來訪問二進位文件是非常有效的。順序讀取文件是很昂貴的,因為現在許多HTTP請求必須通過文件讀取。 對於一些需要順序讀取文件的操作(如複製,DistCp,讀取gzip或其他壓縮格式,解析.csv文件等),順序策略是適當的, 這是默認設置,所以你不需要配置它。
對於高性能隨機訪問IO(例如,訪問ORC文件)的特定情況,您可以考慮在以下情況下使用隨機策略:
- 使用PositionedReadable API讀取數據;
- 要順序讀取很多內容才能夠找到需要的內容;
- 同時需要讀取文件的前面和後面的內容。
- 很少使用單字元read()調用或者少量的緩衝區read(buffer)操作;
- 應用程序的地理位置區域與Amazon S3數據存儲區域在一起或者很近,也就是說,運行應用程序的EC2 VM與Amazon S3存儲區位於同一區域;
實驗性的fadvice策略配置
創建文件系統實例時,必須在配置選項fs.s3a.experimental.input.fadvise中設置所需的fadvise策略,它只能在每個文件系統的基礎上設置,而不能基於每個文件讀取進行設置, 你可以在core-site.xml中設置它:
[html] view plain copy
<property>
<name>
fs.s3a.experimental.input.fadvise</name>
<value>
random</value>
<description>
Policy for reading files.- Values: "random", "sequential" or "normal"
</description>
</property>
也可以在spark-defaults.xml配置文件中進行如下設置:
[html] view plain copy
- spark.hadoop.fs.s3a.experimental.input.fadvise random
請注意,這種隨機訪問性能是以連續IO為代價的 - 這包括讀取使用gzip壓縮的文件。
用S3A快速上傳寫入數據(註:這些優化參數,當前還初於實驗性階段,將來其行為可能會改變)
S3對象存儲的本質,寫入到S3A OutputStream的數據不會是逐步寫入的 - 相反,在默認情況下,它會先緩存到磁碟,直到流的close()方法關閉完成才開始寫入S3中。這可能會使輸出變慢,因為:
- OutputStream.close()的執行時間與緩衝的數據量成正比,與帶寬成反比。那是O(數據/帶寬)。
- 帶寬是從主機到S3的可用帶寬:在上載時同一進程,伺服器或網路中的其他工作可能會增加上傳時間,因此會增加close()調用的持續時間。
- 如果在調用OutputStream.close()之前上載數據的進程失敗,則所有數據都將丟失。
- 承載fs.s3a.buffer.dir中定義的臨時目錄的磁碟必須具有存儲整個緩衝文件的能力。
綜上所述,從S3端點進一步處理的時間越長,或者EC2 VM越小,完成工作的時間就越長。這會在應用程序代碼中造成問題:
- 代碼通常假設close()調用很快;延誤可能會在運營中造成瓶頸。
- 非常緩慢的上傳有時會導致應用程序超時 - 通常,上傳期間線程阻塞會停止報告進度,從而觸發超時。
- 在上傳開始之前,流式傳輸大量數據可能會消耗所有磁碟空間。
解決寫入慢的問題的方案一直在研發之中,目前可以通過「S3A快速上傳」來解決這個問題,要使用這個功能,需要增加一些配置。
「S3A快速上傳」的特點
「S3A快速上傳」特點包括:
- 通過參數fs.s3a.multipart.size設置文件上傳的大小,也就是說,分段上傳開始的閾值和每次上傳的大小是相同的;
- 緩衝區緩衝到磁碟(默認)或堆內內存或堆外內存;
- 後台線程並行上傳塊;
- 一旦緩衝數據超過此分區大小,立即開始上傳塊;
- 將數據緩存到磁碟時,使用fs.s3a.buffer.dir中列出的一個或多個目錄,可以緩衝的數據大小限於可用磁碟空間;
- 生成輸出統計信息作為文件系統的度量標準,包括活動和待處理塊上載的統計信息;
- close()執行的時間由上傳剩餘數據量決定,而不是文件的總大小;
通過塊的增量寫入,「S3A快速上傳」的上傳時間至少與「傳統」機制一樣快,特別是對長時輸出流以及生成大量數據時具有顯著優勢, 內存緩衝機制也可以對S3端點附近運行時提供加速,因為此時中間數據存儲是通過內存而不是磁碟。
啟用「S3A快速上傳」
要啟用快速上載機制,請將fs.s3a.fast.upload屬性設置為true:
[html] view plain copy
<property>
<name>
fs.s3a.fast.upload</name>
<value>
true</value>
<description>
- Use the incremental block upload mechanism with
- the buffering mechanism set in fs.s3a.fast.upload.buffer.
- The number of threads performing uploads in the filesystem is defined
- by fs.s3a.threads.max; the queue of waiting uploads limited by
- fs.s3a.max.total.tasks.
- The size of each buffer is set by fs.s3a.multipart.size.
</description>
</property>
核心配置選項
以下主要配置選項可用於「S3A快速上傳」:
[html] view plain copy
<property>
<name>
fs.s3a.fast.upload.buffer</name>
<value>
disk</value>
<description>
- The buffering mechanism to use when using S3A fast upload
- (fs.s3a.fast.upload=true). Values: disk, array, bytebuffer.
- This configuration option has no effect if fs.s3a.fast.upload is false.
- "disk" will use the directories listed in fs.s3a.buffer.dir as
- the location(s) to save data prior to being uploaded.
- "array" uses arrays in the JVM heap
- "bytebuffer" uses off-heap memory within the JVM.
- Both "array" and "bytebuffer" will consume memory in a single stream up to the number
- of blocks set by: fs.s3a.multipart.size * fs.s3a.fast.upload.active.blocks.
- If using either of these mechanisms, keep this value low
- The total number of threads performing work across all threads is set by
- fs.s3a.threads.max, with fs.s3a.max.total.tasks values setting the number of queued
- work items.
</description>
</property>
<property>
<name>
fs.s3a.multipart.size</name>
<value>
100M</value>
<description>
How big (in bytes) to split upload or copy operations up into.- A suffix from the set {K,M,G,T,P} may be used to scale the numeric value.
</description>
</property>
<property>
<name>
fs.s3a.fast.upload.active.blocks</name>
<value>
8</value>
<description>
- Maximum Number of blocks a single output stream can have
- active (uploading, or queued to the central FileSystem
- instance"s pool of queued operations.
- This stops a single stream overloading the shared thread pool.
</description>
</property>
注意:
- 如果寫入流中的數據量的大小低於fs.s3a.multipart.size中設置的數據量的大小,則上傳將在OutputStream.close()操作完成後執行 - 與原始輸出流一樣。
- 已發布的Hadoop度量標準監視器,包含活動隊列長度和上傳操作計數,以確定何時存在工作積壓或數據生成速率與網路帶寬之間的不匹配情況。每個流的統計信息也可以通過在當前流上調用toString()方法來記錄。
- 增量寫入不可見;只有在close()調用中的多部分操作完成時,才能列出或讀取該對象,在上載完成之前該對象將被阻塞。
使用磁碟緩衝區快速上載
當fs.s3a.fast.upload.buffer設置為磁碟時,所有數據在上載前都會緩存到本地硬碟。這最大限度地減少了消耗的內存量,因此消除了堆大小作為排隊上載中的限制因素 - 與fs.s3a.fast.upload = false時使用的原始「直接到磁碟」緩衝完全一樣。
[html] view plain copy
<property>
<name>
fs.s3a.fast.upload</name>
<value>
true</value>
</property>
<property>
<name>
fs.s3a.fast.upload.buffer</name>
<value>
disk</value>
</property>
<property>
<name>
fs.s3a.buffer.dir</name>
<value></value>
<description>
Comma separated list of temporary directories use for- storing blocks of data prior to their being uploaded to S3.
- When unset, the Hadoop temporary directory hadoop.tmp.dir is used
</description>
</property>
這是默認的緩衝機制, 可以緩衝的數據量受可用磁碟空間量的限制。
使用ByteBuffers快速上傳
當fs.s3a.fast.upload.buffer設置為bytebuffer時,所有數據在上傳前都會緩存在「直接」ByteBuffers中。 這可能比緩衝到磁碟更快,並且如果磁碟空間很小(例如,微小的EC2 VM),可能沒有多少磁碟空間可供緩衝。
ByteBuffers在JVM的內存中創建,但不在Java堆本身中創建。 可以緩衝的數據量由Java運行時,操作系統以及YARN應用程序限制每個容器請求的內存量。
上傳到S3的帶寬越慢,內存耗盡的風險就越大 - 因此在調整上傳線程設置時需要更加小心,以減少可以緩存的等待上載的最大數據量(請參閱下文)。
[html] view plain copy
<property>
<name>
fs.s3a.fast.upload</name>
<value>
true</value>
</property>
<property>
<name>
fs.s3a.fast.upload.buffer</name>
<value>
bytebuffer</value>
</property>
使用Arrays快速上傳
當fs.s3a.fast.upload.buffer設置為Arrays時,所有數據都會在上傳之前緩存在JVM堆中的位元組數組中, 這比緩衝到磁碟更快。
可以緩衝的數據量受JVM堆堆的可用大小的限制, 寫入S3帶寬越慢,堆溢出的風險就越大, 這種風險可以通過調整上傳線程設置來緩解(見下文)。
[html] view plain copy
<property>
<name>
fs.s3a.fast.upload</name>
<value>
true</value>
</property>
<property>
<name>
fs.s3a.fast.upload.buffer</name>
<value>
array</value>
</property>
S3A快速上傳線程調整
數組和位元組緩衝區緩衝機制都會分別消耗大量的堆內或堆外內存,磁碟緩衝機制不佔用太多內存,但會消耗硬碟容量。
如果在單個進程中寫入的輸出流很多,則所用內存或磁碟的數量是所有流的活動內存/磁碟使用量的倍數。
如果想減少內存耗盡的風險,尤其是在數據緩衝在內存中的情況下。有一些可以調整的參數:
- 調整文件系統中可用於數據上載或任何其他排隊文件系統操作的線程總數,這在fs.s3a.threads.max參數中設置;
- 調整排隊等待執行的操作數:fs.s3a.max.total.tasks;
- 調整單個輸出流可以激活的任務塊的數量,即由線程上載或在文件系統線程隊列中排隊的塊數:fs.s3a.fast.upload.active.blocks;
- 空閑線程在退出之前可以留在線程池中多久:fs.s3a.threads.keepalivetime;
- 當達到單個流的活動塊的最大允許數量時,在該活動塊的一個或多個上傳完成之前,不能從該流上傳更多塊。那就是:write()調用會觸發一個現在完整的數據塊的上傳,直到隊列中有容量時才會被阻塞;
結論
- 由於在fs.s3a.threads.max中設置的線程池是共享的(並且打算在所有線程中使用),因此這裡設置較大的數字,就可以允許更多的並行操作。但是由於上傳需要網路帶寬,添加更多線程並不一定能夠保證起到加速作用,因而該參數與當前網路狀況相關;
- 線程池的額外任務隊列(fs.s3a.max.total.tasks)涵蓋了所有正在進行的後台S3A操作(未來計劃包括:並行化重命名操作,非同步目錄操作);
- 當使用內存緩衝時,可以通過設置fs.s3a.fast.upload.active.blocks來限制每個流操作可以使用的內存;
- 使用磁碟緩衝時,設置較大fs.s3a.fast.upload.active.blocks的值,雖然不會消耗太多內存,但它可能導致大量的塊與其他文件系統操作之間的競爭;
我們建議先把fs.s3a.fast.upload.active.blocks的值設置的低一點 - 至少足以啟動後台上傳,但不會使用系統的其他部分超載,然後通過試驗,不斷的調整該值,看看是否能夠提供更高的吞吐量 - 尤其是要針EC2上運行的虛擬機多做些測試。
[html] view plain copy
<property>
<name>
fs.s3a.fast.upload.active.blocks</name>
<value>
4</value>
<description>
- Maximum Number of blocks a single output stream can have
- active (uploading, or queued to the central FileSystem
- instance"s pool of queued operations.
- This stops a single stream overloading the shared thread pool.
</description>
</property>
<property>
<name>
fs.s3a.threads.max</name>
<value>
10</value>
<description>
The total number of threads available in the filesystem for data- uploads *or any other queued filesystem operation*.
</description>
</property>
<property>
<name>
fs.s3a.max.total.tasks</name>
<value>
5</value>
<description>
The number of operations which can be queued for execution</description>
</property>
<property>
<name>
fs.s3a.threads.keepalivetime</name>
<value>
60</value>
<description>
Number of seconds a thread can be idle before being- terminated.
</description>
</property>
改善負載均衡行為
Amazon S3使用一組前端伺服器來提供對底層數據的訪問,有關使用哪個前端伺服器的決定是通過負載均衡DNS服務處理的,當查找Amazon S3存儲桶的IP地址時,根據前端伺服器的當前負載來選擇返回到客戶端的IP地址。
隨著時間的推移,前端的負載會發生變化,因此那些被認為是「輕負載」的伺服器會發生變化,這意味著如果DNS值被緩存了很長時間,應用程序最終可能會與超負荷的伺服器連接;或者在出現故障的情況下,他們最終可能會嘗試與已經不存伺服器連接。
而且,出於歷史安全原因,在小應用程序時代,默認情況下,JVM的DNS TTL設置為「無窮大」。
要改善AWS負載平衡,請將與Amazon S3配合使用的應用程序的DNS生存時間設置為低於默認值的值,這請參閱AWS文檔中的設置DNS名稱查找的JVM TTL。
※XPath、XQuery 以及 XSLT 函數函數參考手冊
※Linux Memcached 安裝
TAG:程序員小新人學習 |