<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-314  評論-209  文章-0  trackbacks-0
     
    如果用傳統SCP遠程拷貝,速度是比較慢的。現在采用lz4壓縮傳輸。LZ4是一個非常快的無損壓縮算法,壓縮速度在單核300MB/S,可擴展支持多核CPU。它還具有一個非常快速的解碼器,速度單核可達到和超越1GB/S。通常能夠達到多核系統上的RAM速度限制。 你PV 全命為Pipe Viewer,利用它我們可以查看到命令執行的進度。 下面介紹下lz4和pv的安裝,下載軟件: 下載pv-1.1.4.tar.gz wget http://sourceforge.jp/projects/sfnet_pipeviewer/downloads/pipeviewer/1.1.4/pv-1.1.4.tar.bz2/ 下lz4的包難一些,可能要FQ:https://dl.dropboxusercontent.com/u/59565338/LZ4/lz4-r108.tar.gz 安裝灰常簡單: pv安裝: [root ~]$ tar jxvf pv-1.1.4.tar.bz2 [root ~]$ cd pv-1.1.4 [root pv-1.1.4]$ ./configure && make && make install lz4安裝: [root ~]$ tar zxvf lz4-r108.tar.gz [root ~]$ cd lz4-r108 [root lz4-r108]$ make && make install 用法:(-c 后指定要傳輸的文件,ssh -p 是指定端口,后面的ip是目標主機的ip, -xC指定傳到目標主機下的那個目錄下,別的不用修改): tar -c mysql-slave-3307 |pv|lz4 -B4|ssh -p10022 -c arcfour128 -o"MACs umac-64@openssh.com" 192.168.100.234 "lz4 -d |tar -xC /data" 下面是我線上傳一個從庫的效果: 看到了吧,25.7G 只需要接近3分鐘,這樣遠比scp速度快上了好幾倍,直接scp拷貝離散文件,很消耗IO,而使用LZ4快速壓縮,對性能影響不大,傳輸速度快 PS:下次補充同機房不同網段的傳輸效果及跨機房的傳輸效果^0^ 作者:陸炫志 出處:xuanzhi的博客 http://www.cnblogs.com/xuanzhi201111 您的支持是對博主最大的鼓勵,感謝您的認真閱讀。本文版權歸作者所有,歡迎轉載,但請保留該聲明。
    posted @ 2017-09-14 18:24 xzc 閱讀(441) | 評論 (0)編輯 收藏
    王 騰騰 和 邵 兵 2015 年 11 月 26 日發布 WeiboGoogle+用電子郵件發送本頁面 Comments 1 引子 隨著云時代的來臨,大數據(Big data)也獲得了越來越多的關注。著云臺的分析師團隊認為,大數據(Big data)通常用來形容一個公司創造的大量非結構化和半結構化數據,這些數據在下載到關系型數據庫用于分析時會花費過多時間和金錢。大數據分析常和云計算聯系到一起,因為實時的大型數據集分析需要像 MapReduce 一樣的框架來向數十、數百或甚至數千的電腦分配工作。 “大數據”在互聯網行業指的是這樣一種現象:互聯網公司在日常運營中生成、累積的用戶網絡行為數據。這些數據的規模是如此龐大,以至于不能用 G 或 T 來衡量。所以如何高效的處理分析大數據的問題擺在了面前。對于大數據的處理優化方式有很多種,本文中主要介紹在使用 Hadoop 平臺中對數據進行壓縮處理來提高數據處理效率。 壓縮簡介 Hadoop 作為一個較通用的海量數據處理平臺,每次運算都會需要處理大量數據,我們會在 Hadoop 系統中對數據進行壓縮處理來優化磁盤使用率,提高數據在磁盤和網絡中的傳輸速度,從而提高系統處理數據的效率。在使用壓縮方式方面,主要考慮壓縮速度和壓縮文件的可分割性。綜合所述,使用壓縮的優點如下: 1. 節省數據占用的磁盤空間; 2. 加快數據在磁盤和網絡中的傳輸速度,從而提高系統的處理速度。 壓縮格式 Hadoop 對于壓縮格式的是自動識別。如果我們壓縮的文件有相應壓縮格式的擴展名(比如 lzo,gz,bzip2 等)。Hadoop 會根據壓縮格式的擴展名自動選擇相對應的解碼器來解壓數據,此過程完全是 Hadoop 自動處理,我們只需要確保輸入的壓縮文件有擴展名。 Hadoop 對每個壓縮格式的支持, 詳細見下表: 表 1. 壓縮格式 壓縮格式 工具 算法 擴展名 多文件 可分割性 DEFLATE 無 DEFLATE .deflate 不 不 GZIP gzip DEFLATE .gzp 不 不 ZIP zip DEFLATE .zip 是 是,在文件范圍內 BZIP2 bzip2 BZIP2 .bz2 不 是 LZO lzop LZO .lzo 不 是 如果壓縮的文件沒有擴展名,則需要在執行 MapReduce 任務的時候指定輸入格式。 1 2 3 4 5 hadoop jar /usr/home/hadoop/hadoop-0.20.2/contrib/streaming/ hadoop-streaming-0.20.2-CD H3B4.jar -file /usr/home/hadoop/hello/mapper.py -mapper / usr/home/hadoop/hello/mapper.py -file /usr/home/hadoop/hello/ reducer.py -reducer /usr/home/hadoop/hello/reducer.py -input lzotest -output result4 - jobconf mapred.reduce.tasks=1*-inputformatorg.apache.hadoop.mapred.LzoTextInputFormat* 性能對比 Hadoop 下各種壓縮算法的壓縮比,壓縮時間,解壓時間見下表: 表 2. 性能對比 壓縮算法 原始文件大小 壓縮文件大小 壓縮速度 解壓速度 gzip 8.3GB 1.8GB 17.5MB/s 58MB/s bzip2 8.3GB 1.1GB 2.4MB/s 9.5MB/s LZO-bset 8.3GB 2GB 4MB/s 60.6MB/s LZO 8.3GB 2.9GB 49.3MB/s 74.6MB/s 因此我們可以得出: 1) Bzip2 壓縮效果明顯是最好的,但是 bzip2 壓縮速度慢,可分割。 2) Gzip 壓縮效果不如 Bzip2,但是壓縮解壓速度快,不支持分割。 3) LZO 壓縮效果不如 Bzip2 和 Gzip,但是壓縮解壓速度最快!并且支持分割! 這里提一下,文件的可分割性在 Hadoop 中是很非常重要的,它會影響到在執行作業時 Map 啟動的個數,從而會影響到作業的執行效率! 所有的壓縮算法都顯示出一種時間空間的權衡,更快的壓縮和解壓速度通常會耗費更多的空間。在選擇使用哪種壓縮格式時,我們應該根據自身的業務需求來選擇。 下圖是在本地壓縮與通過流將壓縮結果上傳到 BI 的時間對比。 圖 1. 時間對比 圖 1. 時間對比 使用方式 MapReduce 可以在三個階段中使用壓縮。 1. 輸入壓縮文件。如果輸入的文件是壓縮過的,那么在被 MapReduce 讀取時,它們會被自動解壓。 2.MapReduce 作業中,對 Map 輸出的中間結果集壓縮。實現方式如下: 1)可以在 core-site.xml 文件中配置,代碼如下 圖 2. core-site.xml 代碼示例 圖 2. core-site.xml 代碼示例 2)使用 Java 代碼指定 1 2 conf.setCompressMapOut(true); conf.setMapOutputCompressorClass(GzipCode.class); 最后一行代碼指定 Map 輸出結果的編碼器。 3.MapReduce 作業中,對 Reduce 輸出的最終結果集壓。實現方式如下: 1)可以在 core-site.xml 文件中配置,代碼如下 圖 3. core-site.xml 代碼示例 圖 3. core-site.xml 代碼示例 2)使用 Java 代碼指定 1 2 conf.setBoolean(“mapred.output.compress”,true); conf.setClass(“mapred.output.compression.codec”,GzipCode.class,CompressionCodec.class); 最后一行同樣指定 Reduce 輸出結果的編碼器。 壓縮框架 我們前面已經提到過關于壓縮的使用方式,其中第一種就是將壓縮文件直接作為入口參數交給 MapReduce 處理,MapReduce 會自動根據壓縮文件的擴展名來自動選擇合適解壓器處理數據。那么到底是怎么實現的呢?如下圖所示: 圖 4. 壓縮實現情形 圖 4. 壓縮實現情形 我們在配置 Job 作業的時候,會設置數據輸入的格式化方式,使用 conf.setInputFormat() 方法,這里的入口參數是 TextInputFormat.class。 TextInputFormat.class 繼承于 InputFormat.class,主要用于對數據進行兩方面的預處理。一是對輸入數據進行切分,生成一組 split,一個 split 會分發給一個 mapper 進行處理;二是針對每個 split,再創建一個 RecordReader 讀取 split 內的數據,并按照的形式組織成一條 record 傳給 map 函數進行處理。此類在對數據進行切分之前,會首先初始化壓縮解壓工程類 CompressionCodeFactory.class,通過工廠獲取實例化的編碼解碼器 CompressionCodec 后對數據處理操作。 下面我們來詳細的看一下從壓縮工廠獲取編碼解碼器的過程。 壓縮解壓工廠類 CompressionCodecFactory 壓縮解壓工廠類 CompressionCodeFactory.class 主要功能就是負責根據不同的文件擴展名來自動獲取相對應的壓縮解壓器 CompressionCodec.class,是整個壓縮框架的核心控制器。我們來看下 CompressionCodeFactory.class 中的幾個重要方法: 1. 初始化方法 圖 5. 代碼示例 圖 5. 代碼示例 ① getCodeClasses(conf) 負責獲取關于編碼解碼器 CompressionCodec.class 的配置信息。下面將會詳細講解。 ② 默認添加兩種編碼解碼器。當 getCodeClass(conf) 方法沒有讀取到相關的編碼解碼器 CompressionCodec.class 的配置信息時,系統會默認添加兩種編碼解碼器 CompressionCodec.class,分別是 GzipCode.class 和 DefaultCode.class。 ③ addCode(code) 此方法用于將編碼解碼器 CompressionCodec.class 添加到系統緩存中。下面將會詳細講解。 2. getCodeClasses(conf) 圖 6. 代碼示例 圖 6. 代碼示例 ① 這里我們可以看,系統讀取關于編碼解碼器 CompressionCodec.class 的配置信息在 core-site.xml 中 io.compression.codes 下。我們看下這段配置文件,如下圖所示: 圖 7. 代碼示例 圖 7. 代碼示例 Value 標簽中是每個編碼解碼 CompressionCodec.class 的完整路徑,中間用逗號分隔。我們只需要將自己需要使用到的編碼解碼配置到此屬性中,系統就會自動加載到緩存中。 除了上述的這種方式以外,Hadoop 為我們提供了另一種加載方式:代碼加載。同樣最終將信息配置在 io.compression.codes 屬性中,代碼如下: 1 2 conf.set("io.compression.codecs","org.apache.hadoop.io.compress.DefaultCodec, org.apache.hadoop.io.compress.GzipCodec,com.hadoop.compression.lzo.LzopCodec");) 3. addCode(code) 方法添加編碼解碼器 圖 8. 代碼示例 圖 8. 代碼示例 addCodec(codec) 方法入口參數是個編碼解碼器 CompressionCodec.class,這里我們會首先接觸到它的一個方法。 ① codec.getDefaultExtension() 方法看方法名的字面意思我們就可以知道,此方法用于獲取此編碼解碼所對應文件的擴展名,比如,文件名是 xxxx.gz2,那么這個方法的返回值就是“.bz2”,我們來看下 org.apache.hadoop.io.compress.BZip2Codec 此方法的實現代碼: 圖 9. 代碼示例 圖 9. 代碼示例 ② Codecs 是一個 SortedMap 的示例。這里有個很有意思的地方,它將 Key 值,也就是通過 codec.getDefaultExtension() 方法獲取到的文件擴展名進行了翻轉,舉個例子,比如文件名擴展名“.bz2”,將文件名翻轉之后就變成了“2zb.”。 系統加載完所有的編碼解碼器后,我們可以得到這樣一個有序映射表,如下: 圖 10. 代碼示例 圖 10. 代碼示例 現在編碼解碼器都有了,我們怎么得到對應的編碼解碼器呢?看下面這個方法。 4. getCodec() 方法 此方法用于獲取文件所對應的的編碼解碼器 CompressionCodec.class。 圖 11. 代碼示例 圖 11. 代碼示例 getCodec(Path) 方法的輸入參數是 Path 對象,保存著文件路徑。 ① 將文件名翻轉。如 xxxx.bz2 翻轉成 2zb.xxxx。 ② 獲取 codecs 集合中最接近 2zb.xxxx 的值。此方法有返回值同樣是個 SortMap 對象。 在這里對返回的 SortMap 對象進行第二次篩選。 編碼解碼器 CompressionCodec 剛剛在介紹壓縮解壓工程類 CompressionCodeFactory.class 的時候,我們多次提到了壓縮解壓器 CompressionCodecclass,并且我們在上文中還提到了它其中的一個用于獲取文件擴展名的方法 getDefaultExtension()。 壓縮解壓工程類 CompressionCodeFactory.class 使用的是抽象工廠的設計模式。它是一個接口,制定了一系列方法,用于創建特定壓縮解壓算法。下面我們來看下比較重要的幾個方法: 1. createOutputStream() 方法對數據流進行壓縮。 圖 12. 代碼示例 圖 12. 代碼示例 此方法提供了方法重載。 ① 基于流的壓縮處理; ② 基于壓縮機 Compress.class 的壓縮處理 2. createInputStream() 方法對數據流進行解壓。 圖 13. 代碼示例 圖 13. 代碼示例 這里的解壓方法同樣提供了方法重載。 ① 基于流的解壓處理; ② 基于解壓機 Decompressor.class 的解壓處理; 關于壓縮/解壓流與壓縮/解壓機會在下面的文章中我們會詳細講解。此處暫作了解。 3. getCompressorType() 返回需要的編碼器的類型。 getDefaultExtension() 獲取對應文件擴展名的方法。前文已提到過,不再敖述。 壓縮機 Compressor 和解壓機 Decompressor 前面在編碼解碼器部分的 createInputStream() 和 createInputStream() 方法中我們提到過 Compressor.class 和 Decompressor.class 對象。在 Hadoop 的實現中,數據編碼器和解碼器被抽象成了兩個接口: 1. org.apache.hadoop.io.compress.Compressor; 2. org.apache.hadoop.io.compress.Decompressor; 它們規定了一系列的方法,所以在 Hadoop 內部的編碼/解碼算法實現都需要實現對應的接口。在實際的數據壓縮與解壓縮過程,Hadoop 為用戶提供了統一的 I/O 流處理模式。 我們看一下壓縮機 Compressor.class,代碼如下: 圖 14. 代碼示例 圖 14. 代碼示例 ① setInput() 方法接收數據到內部緩沖區,可以多次調用; ② needsInput() 方法用于檢查緩沖區是否已滿。如果是 false 則說明當前的緩沖區已滿; ③ getBytesRead() 輸入未壓縮字節的總數; ④ getBytesWritten() 輸出壓縮字節的總數; ⑤ finish() 方法結束數據輸入的過程; ⑥ finished() 方法用于檢查是否已經讀取完所有的等待壓縮的數據。如果返回 false,表明壓縮器中還有未讀取的壓縮數據,可以繼續通過 compress() 方法讀取; ⑦ compress() 方法獲取壓縮后的數據,釋放緩沖區空間; ⑧ reset() 方法用于重置壓縮器,以處理新的輸入數據集合; ⑨ end() 方法用于關閉解壓縮器并放棄所有未處理的輸入; ⑩ reinit() 方法更進一步允許使用 Hadoop 的配置系統,重置并重新配置壓縮器; 為了提高壓縮效率,并不是每次用戶調用 setInput() 方法,壓縮機就會立即工作,所以,為了通知壓縮機所有數據已經寫入,必須使用 finish() 方法。finish() 調用結束后,壓縮機緩沖區中保持的已經壓縮的數據,可以繼續通過 compress() 方法獲得。至于要判斷壓縮機中是否還有未讀取的壓縮數據,則需要利用 finished() 方法來判斷。 壓縮流 CompressionOutputStream 和解壓縮流 CompressionInputStream 前文編碼解碼器部分提到過 createInputStream() 方法返回 CompressionOutputStream 對象,createInputStream() 方法返回 CompressionInputStream 對象。這兩個類分別繼承自 java.io.OutputStream 和 java.io.InputStream。從而我們不難理解,這兩個對象的作用了吧。 我們來看下 CompressionInputStream.class 的代碼: 圖 15. 代碼示例 圖 15. 代碼示例 可以看到 CompressionOutputStream 實現了 OutputStream 的 close() 方法和 flush() 方法,但用于輸出數據的 write() 方法以及用于結束壓縮過程并將輸入寫到底層流的 finish() 方法和重置壓縮狀態的 resetState() 方法還是抽象方法,需要 CompressionOutputStream 的子類實現。 Hadoop 壓縮框架中為我們提供了一個實現了 CompressionOutputStream 類通用的子類 CompressorStream.class。 圖 16. 代碼示例 圖 16. 代碼示例 CompressorStream.class 提供了三個不同的構造函數,CompressorStream 需要的底層輸出流 out 和壓縮時使用的壓縮器,都作為參數傳入構造函數。另一個參數是 CompressorStream 工作時使用的緩沖區 buffer 的大小,構造時會利用這個參數分配該緩沖區。第一個可以手動設置緩沖區大小,第二個默認 512,第三個沒有緩沖區且不可使用壓縮器。 圖 17. 代碼示例 圖 17. 代碼示例 在 write()、compress()、finish() 以及 resetState() 方法中,我們發現了壓縮機 Compressor 的身影,前面文章我們已經介紹過壓縮機的的實現過程,通過調用 setInput() 方法將待壓縮數據填充到內部緩沖區,然后調用 needsInput() 方法檢查緩沖區是否已滿,如果緩沖區已滿,將調用 compress() 方法對數據進行壓縮。流程如下圖所示: 圖 18. 調用流程圖 圖 18. 調用流程圖 結束語 本文深入到 Hadoop 平臺壓縮框架內部,對其核心代碼以及各壓縮格式的效率進行對比分析,以幫助讀者在使用 Hadoop 平臺時,可以通過對數據進行壓縮處理來提高數據處理效率。當再次面臨海量數據處理時, Hadoop 平臺的壓縮機制可以讓我們事半功倍。 相關主題 Hadoop 在線 API 《Hadoop 技術內幕深入解析 HADOOP COMMON 和 HDFS 架構設計與實現原理》 developerWorks 開源技術主題:查找豐富的操作信息、工具和項目更新,幫助您掌握開源技術并將其用于 IBM 產品。
    posted @ 2017-09-14 17:35 xzc 閱讀(560) | 評論 (0)編輯 收藏

    Linux系統查看當前主機CPU、內存、機器型號及主板信息:


    查看CPU信息(型號)
    # cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c

     

    查看內存信息
    # cat /proc/meminfo

     

    查看主板型號:
    # dmidecode |grep -A16 "System Information$"

     

    查看機器型號
    # dmidecode | grep "Product Name"

     

    查看當前操作系統內核信息
    # uname -a

     

    查看當前操作系統發行版信息
    # cat /etc/issue | grep Linux

    posted @ 2017-09-10 16:37 xzc 閱讀(247) | 評論 (0)編輯 收藏
    本文介紹Hadoop YARN最近版本中增加的幾個非常有用的特性,包括: (1)ResourceManager HA 在apache hadoop 2.4或者CDH5.0.0版本之后,增加了ResourceManger HA特性,支持基于Zookeeper的熱主備切換,具體配置參數可以參考Cloudera的文檔:ResourceManager HA配置。 需要注意的是,ResourceManager HA只完成了第一個階段的設計,即備ResourceManager啟動后,會殺死之前正在運行的Application,然后從共享存儲系統中讀取這些Application的元數據信息,并重新提交這些Application。啟動ApplicationMaster后,剩下的容錯功能就交給ApplicationMaster實現了,比如MapReduce的ApplicationMaster會不斷地將完成的任務信息寫到HDFS上,這樣,當它重啟時,可以重新讀取這些日志,進而只需重新運行那些未完成的任務。ResourceManager HA第二個階段的任務是,備ResourceManager接管主ResourceManager后,無需殺死那些正在運行的Application,讓他們像任何事情沒有發生一樣運行下去。 (2) 磁盤容錯 在apache hadoop 2.4或者CDH5.0.0版本之后,增加了幾個對多磁盤非常友好地參數,這些參數允許YARN更好地使用NodeManager上的多塊磁盤,相關jira為:YARN-1781,主要新增了三個參數: yarn.nodemanager.disk-health-checker.min-healthy-disks:NodeManager上最少保證健康磁盤比例,當健康磁盤比例低于該值時,NodeManager不會再接收和啟動新的Container,默認值是0.25,表示25%; yarn.nodemanager.disk-health-checker.max-disk-utilization-per-disk-percentage:一塊磁盤的最高使用率,當一塊磁盤的使用率超過該值時,則認為該盤為壞盤,不再使用該盤,默認是100,表示100%,可以適當調低; yarn.nodemanager.disk-health-checker.min-free-space-per-disk-mb:一塊磁盤最少保證剩余空間大小,當某塊磁盤剩余空間低于該值時,將不再使用該盤,默認是0,表示0MB。 (3)資源調度器 Fair Scheduler:Fair Scheduler增加了一個非常有用的新特性,允許用戶在線將一個應用程序從一個隊列轉移到另外一個隊列,比如將一個重要作業從一個低優先級隊列轉移到高優先級隊列,操作命令是:bin/yarn application -movetoqueue appID -queue targetQueueName,相關jira為:YARN-1721。 Capacity Scheduler:Capacity Scheduler中資源搶占功能經過了充分的測試,可以使用了。 原創文章,轉載請注明: 轉載自董的博客 本文鏈接地址: http://dongxicheng.org/mapreduce-nextgen/hadoop-yarn-recently-new-features/
    posted @ 2017-09-07 11:37 xzc 閱讀(277) | 評論 (0)編輯 收藏
    關于mapreduce程序運行在yarn上時內存的分配一直是一個讓我蒙圈的事情,單獨查任何一個資料都不能很好的理解透徹。于是,最近查了大量的資料,綜合各種解釋,終于理解到了一個比較清晰的程度,在這里將理解的東西做一個簡單的記錄,以備忘卻。 首先,先將關于mapreduce和yarn關于內存分配的參數粘貼上: yarn.scheduler.minimum-allocation-mb yarn.scheduler.maximum-allocation-mb yarn.nodemanager.resource.memory-mb yarn.nodemanager.vmem-pmem-ratio yarn.scheduler.increment-allocation-mb mapreduce.map.memory.mb mapreduce.reduce.memory.mb mapreduce.map.java.opts mapreduce.reduce.java.opts 個人認為,針對mapreduce任務,這些參數只有放在一起學習才能真正理解,如果單獨考慮,理解不清晰。下面開始詳細講解。 一、理解參數yarn.nodemanager.resource.memory-mb,yarn.nodemanager.vmem-pmem-ratio yarn.nodemanager.resource.memory-mb很簡單,就是你的這臺服務器節點上準備分給yarn的內存; yarn.nodemanager.vmem-pmem-ratio網上解釋都是"每使用1MB物理內存,最多可用的虛擬內存數,默認2.1",但是目前我還是不太理解其作用是什么,有知道的朋友希望能詳細解釋下。 二、理解參數yarn.scheduler.minimum-allocation-mb和yarn.scheduler.maximum-allocation-mb 都知道,在yarn上運行程序時每個task都是在獨立的Container中運行的,單個Container可以申請的最小和最大內存的限制就是這兩個參數,注意,并不是這兩個參數決定單個Container申請內存的大小,而僅僅是限制的一個范圍。 三、理解yarn的內存規整化因子和內存規整化算法 先不說和哪個參數有關,單純理解這一概念。舉例: 假如規整化因子b=512M,上述講的參數yarn.scheduler.minimum-allocation-mb為1024,yarn.scheduler.maximum-allocation-mb為8096,然后我打算給單個map任務申請內存資源(mapreduce.map.memory.mb): 申請的資源為a=1000M時,實際得到的Container內存大小為1024M(小于yarn.scheduler.minimum-allocation-mb的話自動設置為yarn.scheduler.minimum-allocation-mb); 申請的資源為a=1500M時,實際得到的Container內存大小為1536M,計算公式為:ceiling(a/b)*b,即ceiling(a/b)=ceiling(1500/512)=3,3*512=1536。此處假如b=1024,則Container實際內存大小為2048M 也就是說Container實際內存大小最小為yarn.scheduler.minimum-allocation-mb值,然后增加時的最小增加量為規整化因子b,最大不超過yarn.scheduler.maximum-allocation-mb 四、理解mapreduce.map.memory.mb、mapreduce.reduce.memory.mb "三"中提到的"打算給單個map任務申請內存資源"也就是a,其實就是指的"mapreduce.map.memory.mb"或"mapreduce.reduce.memory.mb",注意其值不要超過yarn.scheduler.maximum-allocation-mb 五、理解mapreduce.map.java.opts、mapreduce.reduce.java.opts 以map任務為例,Container其實就是在執行一個腳本文件,而腳本文件中,會執行一個 Java 的子進程,這個子進程就是真正的 Map Task,mapreduce.map.java.opts 其實就是啟動 JVM 虛擬機時,傳遞給虛擬機的啟動參數,而默認值 -Xmx200m 表示這個 Java 程序可以使用的最大堆內存數,一旦超過這個大小,JVM 就會拋出 Out of Memory 異常,并終止進程。而 mapreduce.map.memory.mb 設置的是 Container 的內存上限,這個參數由 NodeManager 讀取并進行控制,當 Container 的內存大小超過了這個參數值,NodeManager 會負責 kill 掉 Container。在后面分析 yarn.nodemanager.vmem-pmem-ratio 這個參數的時候,會講解 NodeManager 監控 Container 內存(包括虛擬內存和物理內存)及 kill 掉 Container 的過程。 也就是說,mapreduce.map.java.opts一定要小于mapreduce.map.memory.mb mapreduce.reduce.java.opts同mapreduce.map.java.opts一樣的道理。 六、理解規整化因子指的是哪個參數 "三"中提到的規整化因子也就是b,具體指的是哪個參數和yarn使用的調度器有關,一共有三種調度器:capacity scheduler(默認調度器)、fair scheduler和fifo scheduler 當使用capacity scheduler或者fifo scheduler時,規整化因子指的就是參數yarn.scheduler.minimum-allocation-mb,不能單獨配置,即yarn.scheduler.increment-allocation-mb無作用; 當使用fair scheduler時,規整化因子指的是參數yarn.scheduler.increment-allocation-mb 至此,關于yarn和mapreduce的任務內存配置問題講完了,這也是我目前理解的層次。
    posted @ 2017-08-30 21:05 xzc 閱讀(308) | 評論 (0)編輯 收藏
    1. 日期輸出格式化

    所有日期、時間的api都在datetime模塊內。

    1. datetime => string

    now = datetime.datetime.now()
    now.strftime('%Y-%m-%d %H:%M:%S')
    #輸出2012-03-05 16:26:23.870105

    strftime是datetime類的實例方法。

    2. string => datetime

    t_str = '2012-03-05 16:26:23'
    d = datetime.datetime.strptime(t_str, '%Y-%m-%d %H:%M:%S')

    strptime是datetime類的靜態方法。

    2. 日期比較操作

    在datetime模塊中有timedelta類,這個類的對象用于表示一個時間間隔,比如兩個日期或者時間的差別。

    構造方法:

    datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)

    所有的參數都有默認值0,這些參數可以是int或float,正的或負的。

    可以通過timedelta.days、tiemdelta.seconds等獲取相應的時間值。

    timedelta類的實例,支持加、減、乘、除等操作,所得的結果也是timedelta類的實例。比如:

    year = timedelta(days=365)
    ten_years = year *10
    nine_years = ten_years - year

    同時,date、time和datetime類也支持與timedelta的加、減運算。

    datetime1 = datetime2 +/- timedelta
    timedelta = datetime1 - datetime2

    這樣,可以很方便的實現一些功能。

    1. 兩個日期相差多少天。

    d1 = datetime.datetime.strptime('2012-03-05 17:41:20', '%Y-%m-%d %H:%M:%S')
    d2 = datetime.datetime.strptime('2012-03-02 17:41:20', '%Y-%m-%d %H:%M:%S')
    delta = d1 - d2
    print delta.days

    輸出:3

    2. 今天的n天后的日期。

    now = datetime.datetime.now()
    delta = datetime.timedelta(days=3)
    n_days = now + delta
    print n_days.strftime('%Y-%m-%d %H:%M:%S')

    輸出:2012-03-08 17:44:50

    復制代碼
    #coding=utf-8
    import datetime
    now=datetime.datetime.now()
    print now
    #將日期轉化為字符串 datetime => string
    print now.strftime('%Y-%m-%d %H:%M:%S')
    
    t_str = '2012-03-05 16:26:23'
    #將字符串轉換為日期 string => datetime
    d=datetime.datetime.strptime(t_str,'%Y-%m-%d %H:%M:%S')
    print d
    
    #在datetime模塊中有timedelta類,這個類的對象用于表示一個時間間隔,比如兩個日#期或者時間的差別。
    
    #計算兩個日期的間隔
    d1 = datetime.datetime.strptime('2012-03-05 17:41:20', '%Y-%m-%d %H:%M:%S')
    d2 = datetime.datetime.strptime('2012-03-02 17:41:20', '%Y-%m-%d %H:%M:%S')
    delta = d1 - d2
    print delta.days
    print delta
    
    #今天的n天后的日期。
    now=datetime.datetime.now()
    delta=datetime.timedelta(days=3)
    n_days=now+delta
    print n_days.strftime('%Y-%m-%d %H:%M:%S')
    復制代碼
    posted @ 2017-08-14 23:09 xzc 閱讀(1369) | 評論 (0)編輯 收藏

    Shell中并沒有真正意義的多線程,要實現多線程可以啟動多個后端進程,最大程度利用cpu性能。

    直接看代碼示例吧。

    (1) 順序執行的代碼

    復制代碼
     1 #!/bin/bash  2 date  3 for i in `seq 1 5`  4 do  5 {  6     echo "sleep 5"  7     sleep 5  8 }  9 done 10 date 
    復制代碼

    輸出:

    復制代碼
    Sat Nov 19 09:21:51 CST 2016 sleep 5 sleep 5 sleep 5 sleep 5 sleep 5 Sat Nov 19 09:22:16 CST 2016
    復制代碼

    (2) 并行代碼

    使用'&'+wait 實現“多進程”實現

    復制代碼
     1 #!/bin/bash  2 date  3 for i in `seq 1 5`  4 do  5 {  6     echo "sleep 5"  7     sleep 5  8 } &  9 done 10 wait  ##等待所有子后臺進程結束 11 date
    復制代碼

    輸出:

    復制代碼
    Sat Nov 19 09:25:07 CST 2016 sleep 5 sleep 5 sleep 5 sleep 5 sleep 5 Sat Nov 19 09:25:12 CST 2016
    復制代碼

     (3) 對于大量處理任務如何實現啟動后臺進程的數量可控?

      簡單的方法可以使用2層for/while循環實現,每次wait內層循環的多個后臺程序執行完成

      但是這種方式的問題是,如果內層循環有“慢節點”可能導致整個任務的執行執行時間長。

      更高級的實現可以看(4)

    (4) 使用命名管道(fifo)實現每次啟動后臺進程數量可控。 

    復制代碼
     1 #!/bin/bash  2   3 function my_cmd(){  4     t=$RANDOM  5     t=$[t%15]  6     sleep $t  7     echo "sleep $t s"  8 }  9  10 tmp_fifofile="/tmp/$$.fifo"  11 mkfifo $tmp_fifofile      # 新建一個fifo類型的文件 12 exec 6<>$tmp_fifofile     # 將fd6指向fifo類型 13 rm $tmp_fifofile    #刪也可以 14  15 thread_num=5  # 最大可同時執行線程數量 16 job_num=100   # 任務總數 17  18 #根據線程總數量設置令牌個數 19 for ((i=0;i<${thread_num};i++));do 20     echo 21 done >&6  22  23 for ((i=0;i<${job_num};i++));do # 任務數量 24     # 一個read -u6命令執行一次,就從fd6中減去一個回車符,然后向下執行, 25     # fd6中沒有回車符的時候,就停在這了,從而實現了線程數量控制 26     read -u6  27  28     #可以把具體的需要執行的命令封裝成一個函數 29     {    30         my_cmd 31     } & 32  33     echo >&6 # 當進程結束以后,再向fd6中加上一個回車符,即補上了read -u6減去的那個 34 done 35  36 wait 37 exec 6>&- # 關閉fd6 38 echo "over"
    復制代碼

     

    參考:http://lawrence-zxc.github.io/2012/06/16/shell-thread/

    posted @ 2017-08-02 17:01 xzc 閱讀(356) | 評論 (0)編輯 收藏

    之前在論壇看到一個關于HDFS權限的問題,當時無法回答該問題。無法回答并不意味著對HDFS權限一無所知,而是不能準確完整的闡述HDFS權限,因此決定系統地學習HDFS文件權限。HDFS的文件和目錄權限模型共享了POSIX(Portable Operating System Interface,可移植操作系統接口)模型的很多部分,比如每個文件和目錄與一個擁有者和組相關聯,文件或者目錄對于擁有者、組內的其它用戶和組外的其它用戶有不同的權限等。與POSIX模型不同的是,HDFS中的文件沒有可執行文件的概念,因而也沒有setuid和setgid,雖然目錄依然保留著可執行目錄的概念(x),但對于目錄也沒有setuid和setgid。粘貼位(sticky bit)可以用在目錄上,用于阻止除超級用戶,目錄或文件的擁有者外的任何刪除或移動目錄中的文件,文件上的粘貼位不起作用。

          當創建文件或目錄時,擁有者為運行客戶端進程的用戶,組為父目錄所屬的組。每個訪問HDFS的客戶端進程有一個由用戶姓名和組列表兩部分組的成標識,無論何時HDFS必須對由客戶端進程訪問的文件或目錄進行權限檢查,規則如下:

     

    • 如果進程的用戶名匹配文件或目錄的擁有者,那么測試擁有者權限
    • 否則如果文件或目錄所屬的組匹配組列表中任何組,那么測試組權限
    • 否則測試其它權限

     

          如果權限檢查失敗,則客戶端操作失敗。

          從hadoop-0.22開始,hadoop支持兩種不同的操作模式以確定用戶,分別為simple和kerberos具體使用哪個方式由參數hadoop.security.authentication設置,該參數位于core-site.xml文件中,默認值為simple。在simple模式下,客戶端進程的身份由主機的操作系統確定,比如在類Unix系統中,用戶名為命令whoami的輸出。在kerberos模式下,客戶端進程的身份由Kerberos憑證確定,比如在一個Kerberized環境中,用戶可能使用kinit工具得到了一個Kerberos ticket-granting-ticket(TGT)且使用klist確定當前的principal。當映射一個Kerberosprincipal到HDFS的用戶名時,除了最主要的部分外其余部分都被丟棄,比如一個principal為todd/foobar@CORP.COMPANY.COM,將映射為HDFS上的todd。無論哪種操作模式,對于HDFS來說用戶標識機制都是外部的,HDFS本身沒有創建用戶標,建立組或者處理用戶憑證的規定。

          上面討論了確定用戶的兩種模式,即simple和kerberos,下面學習如何確定用戶組。用戶組是通過由參數hadoop.security.group.mapping設置的組映射服務確定的,默認實現是org.apache.hadoop.security.JniBasedUnixGroupsMappingWithFallback,該實現首先確定Java本地接口(JNI)是否可用,如果JNI可用,該實現將使用hadoop中的API為用戶解析用戶組列表。如果JNI不可用,那么使用ShellBasedUnixGroupsMapping,該實現將使用Linux/Unix中的bash –cgroups命令為用戶解析用戶組列表。其它實現還有LdapGroupsMapping,通過直接連接LDAP服務器來解析用戶組列表。對HDFS來說,用戶到組的映射是在NameNode上執行的,因而NameNode的主機系統配置決定了用戶的組映射。HDFS將文件或目錄的用戶和組存儲為字符串,并且不像Linux/Unix那樣可以將用戶和組轉換為數字。

          每個針對文件或者目錄的操作都將全路徑名稱傳遞到NameNode,然后對該路徑的每次操作都將應用權限檢查。客戶端隱含地關聯用戶身份到NameNode的連接,減少改變現存客戶端API的需要。總是存在這么一種情景,當在一個文件上的操作成功后,當重復該操作時可能失敗,因為該文件或者路徑中的某些目錄已經不再存在。例如,當客戶端第一次開始讀取一個文件時,它向NameNode發出的第一個請求來發現該文件第一個塊的位置,第二個尋找其他塊的請求可能失敗。另一方面,對于已經知道文件塊的客戶端來說,刪除文件不會取消訪問。通過添加權限,客戶端對文件的訪問在請求之間可能撤回,對于已經知道文件塊的客戶端來說,改變權限不會取消客戶端的訪問。

          HDFS中超級用戶與通常熟悉的Linux或Unix中的root用戶不同,HDFS的超級用戶是與NameNode進程有相同標示的用戶,更簡單易懂些,啟動NameNode的用戶就為超級用戶。對于誰是超級用戶沒有固定的定義,當NameNode啟動后,該進程的標示決定了誰是超級用戶。HDFS的超級用戶不必是NameNode主機的超級用戶,也需用所有的集群使用相同的超級用戶,出于實驗目的在個人工作站上運行HDFS的人自然而然的稱為超級用戶而不需要任何配置。另外參數dfs.permissions.superusergroup設置了超級用戶,該組中的所有用戶也為超級用戶。超級用戶在HDFS中可以執行任何操作而針對超級用戶的權限檢查永遠不會失敗。

          HDFS也提供了對POSIX ACL(訪問控制列表)支持來為特定的用戶或者用戶組提供更加細粒度的文件權限。ACL是不同于用戶和組的自然組織層次的有用的權限控制方式,ACL可以為特定的用戶和組設置不同的權限,而不僅僅是文件的擁有者和文件所屬的組。默認情況下,HDFS禁用ACL,因此NameNode禁止ACL的創建,為了啟用ACL,需要在hdfs-site.xml中將參數dfs.namenode.acls.enabled設置為true。

          訪問控制列表由一組ACL項組成,每個ACL項命名了特定的用戶或組,并為其授予或拒絕讀,寫和執行的權限,例如:

     

    user::rw- user:bruce:rwx                  #effective:r-- group::r-x                      #effective:r-- group:sales:rwx                 #effective:r-- mask::r-- other::r-- 

     

          每個ACL項由類型,可選的名稱和權限字符串組成,它們之間使用冒號(:)。在上面的例子中文件的擁有者具有讀寫權限,文件所屬的組具有讀和執行的權限,其他用戶具有讀權限,這些設置與將文件設置為654等價(6表示擁有者的讀寫權限,5表示組的讀和執行權限,4表示其他用戶的讀權限)。除此之外,還有兩個擴展的ACL項,分別為用戶bruce和組sales,并都授予了讀寫和執行的權限。mask項是一個特殊的項,用于過濾授予所有命名用戶,命名組及未命名組的權限,即過濾除文件擁有者和其他用戶(other)之外的任何ACL項。在該例子中,mask值有讀權限,則bruce用戶、sales組和文件所屬的組只具有讀權限。每個ACL必須有mask項,如果用戶在設置ACL時沒有使用mask項,一個mask項被自動加入到ACL中,該mask項是通過計算所有被mask過濾項的權限與(&運算)得出的。對擁有ACL的文件執行chmod實際改變的是mask項的權限,因為mask項扮演的是過濾器的角色,這將有效地約束所有擴展項的權限,而不是僅改變組的權限而可能漏掉其它擴展項的權限。

          訪問控制列表和默認訪問控制列表存在著不同,前者定義了在執行權限檢查實施的規則,后者定義了新文件或者子目錄創建時自動接收的ACL項,例如:

    user::rwx group::r-x other::r-x default:user::rwx default:user:bruce:rwx          #effective:r-x default:group::r-x default:group:sales:rwx         #effective:r-x default:mask::r-x default:other::r-x 

          只有目錄可能擁有默認訪問控制列表,當創建新文件或者子目錄時,自動拷貝父輩的默認訪問控制列表到自己的訪問控制列表中,新的子目錄也拷貝父輩默認的訪問控制列表到自己的默認訪問控制列表中。這樣,當創建子目錄時默認ACL將沿著文件系統樹被任意深層次地拷貝。在新的子ACL中,準確的權限由模式參數過濾。默認的umask為022,通常新目錄權限為755,新文件權限為644。模式參數為未命名用戶(文件的擁有者),mask及其他用戶過濾拷貝的權限值。在上面的例子中,創建權限為755的子目錄時,模式對最終結果沒有影響,但是如果創建權限為644的文件時,模式過濾器導致新文件的ACL中文件擁有者的權限為讀寫,mask的權限為讀以及其他用戶權限為讀。mask的權限意味著用戶bruce和組sales只有讀權限。拷貝ACL發生在文件或子目錄的創建時,后面如果修改父輩的默認ACL將不再影響已存在子類的ACL。

          默認ACL必須包含所有最小要求的ACL項,包括文件擁有者項,文件所屬的組項和其它用戶項。如果用戶沒有在默認ACL中配置上述三項中的任何一個,那么該項將通過從訪問ACL拷貝對應的權限來自動插入,或者如果沒有訪問ACL則自動插入權限位。默認ACL也必須擁有mask,如果mask沒有被指定,通過計算所有被mask過濾項的權限與(&運算)自動插入mask。當一個文件擁有ACL時,權限檢查的算法變為:

     

    • 如果用戶名匹配文件的擁有者,則測試擁有者權限
    • 否則,如果用戶名匹配命名用戶項中的用戶名,則測試由mask權限過濾后的該項的權限
    • 否則,如果文件所屬的組匹配組列表中的任何組,并且如果這些被mask過濾的權限具有訪問權限,那么使用這么權限
    • 否則,如果存在命名組項匹配組列表中的成員,并且如果這些被mask過濾的權限具有訪問權限,那么使用這么權限
    • 否則,如果文件所屬的組或者任何命名組項匹配組列表中的成員,但不具備訪問權限,那么訪問被拒絕
    • 否則測試文件的其他用戶權限

     

          最佳實踐時基于傳統的權限位設置大部分權限要求,然后定義少量帶有特殊規則的ACL增加權限位。相比較只是用權限位的文件,使用ACL的文件會在NameNode中產生額外的內存消耗。

          上面學習了HDFS中的文件權限和訪問控制列表,最后學習一下如何針對權限和ACL進行配置,下表列出了其中的重要參數:

    參數名

    位置

    用途

    dfs.permissions.enabled

    hdfs-site.xml

    默認值為true,即啟用權限檢查。如果為 false,則禁用權限檢查。

    hadoop.http.staticuser.user

    core-site.xml

    默認值為dr.who,查看web UI的用戶

    dfs.permissions.superusergroup

    hdfs-site.xml

    超級用戶的組名稱,默認為supergroup

    <fs.permissions.umask-mode

    core-site.xml

    創建文件和目錄時使用的umask,默認值為八進制022,每位數字對應了擁有者,組和其他用戶。該值既可以使用八進制數字,如022,也可以使用符號,如u=rwx,g=r-x,o=r-x(對應022)

    dfs.cluster.administrators

    hdfs-site.xml

    被指定為ACL的集群管理員

    dfs.namenode.acls.enabled

    hdfs-site.xml

    默認值為false,禁用ACL,設置為true則啟用ACL。當ACL被禁用時,NameNode拒絕設置或者獲取ACL的請求

    posted @ 2017-07-28 10:55 xzc 閱讀(981) | 評論 (0)編輯 收藏
    1. crontab 命令:用于在某個時間,系統自動執行你所希望的程序文件或命令。
    2. crontab 的參數
            -e      (edit user's crontab)
            -l      (list user's crontab)
            -r      (delete user's crontab)
            -i      (prompt before deleting user's crontab)
    3.下面進行一個例子:在8月6號18時每隔3分鐘執行以下命令:who >> /apple/test_crontab.log
       步驟一:先創建一個文件cronfile:內容為如下:
               */3 18 6 8 * who >> /apple/test_crontab_log
       步驟二:將文件cronfile 加入到cron守護進行(命令為:crontab cronfile)
    4. 檢查是否加入到守護進程cron中,用命令:crontab -l
       如何出來的內容中包含你剛剛的內容,則加入成功。每隔3分鐘查看下test_crontab.log文件,看看是否有內容。
    5. 對crontab內容格式的解釋:f1 f2 f3 f4 f5 program
       f1 是表示分鐘(0-59),f2 表示小時(0-23),f3 表示一個月份中的第幾日(1-(31、30、29、28)),f4 表示月份(1-12),f5 表示一個星期中的第幾天(0-6(0表示周日))。program 表示要執行的程式(可以理解為文件或命令)
       f1:為*時候表示每隔1分鐘,如果為*/n 表示每隔n分鐘,如果為3,4 表示第3,4分鐘,如果為2-6表示第2分鐘到第6分鐘。
       f2:為*時候表示每隔1小說。如果為*/n 表示每隔n小時,如果為3,4 表示第3,4小時,如果為2-6表示第2小時到第6小時
       f3: 為*時候表示每天。n 表示第n天
       f4: 為*時候表示每月。n 表示第n個月
       f5: 為*時候表示每周。0表示周日,6表示周六,1-4表示周一到周六
    6. 具體例子:(來自crontab百度百科)
       a. 每月每天每小時的第 0 分鐘執行一次 /bin/ls :   0 * * * * /bin/ls   
       b. 在 12 月內, 每天的早上 6 點到 12 點中,每隔 20 分鐘執行一次 /usr/bin/backup :
          */20 6-12 * 12 * /usr/bin/backup  
      c. 周一到周五每天下午 5:00 寄一封信給 alex_mail_name :  
          0 17 * * 1-5 mail -s "hi" alex_mail_name < /tmp/maildata   
       d. 每月每天的午夜 0 點 20 分, 2 點 20 分, 4 點 20 分....執行 echo "haha"   
          20 0-23/2 * * * echo "haha"   
       e. 晚上11點到早上8點之間每兩個小時和早上8點 顯示日期  0 23-7/2,8 * * * date 
    posted @ 2017-07-27 18:59 xzc 閱讀(308) | 評論 (0)編輯 收藏
    最近一段時間,在處理Shell 腳本時候,遇到時間的處理問題。 時間的加減,以及時間差的計算。 
     
    1。 時間加減
     
    這里處理方法,是將基礎的時間轉變為時間戳,然后,需要增加或者改變時間,變成 秒。 
     
    如:1990-01-01 01:01:01  加上 1小時 20分
    處理方法:
    a.將基礎時間轉為時間戳
    time1=$(date +%s -d '1990-01-01 01:01:01')
    echo $time1
    631126861 【時間戳】
     
    b.將增加時間變成秒
    [root@localhost ~]# time2=$((1*60*60+20*60))
    [root@localhost ~]# echo $time2
    4800
     
    c.兩個時間相加,計算出結果時間
    time1=$(($time1+$time2))
    time1=$(date +%Y-%m-%d\ %H:%M:%S -d "1970-01-01 UTC $time1 seconds");
    echo $time1
    1990-01-01 02:21:01
     
    2。時間差計算方法
     
    如:2010-01-01 與 2009-01-01 11:11:11 時間差
    原理:同樣轉成時間戳,然后計算天,時,分,秒
     
    time1=$(($(date +%s -d '2010-01-01') - $(date +%s -d '2009-01-01 11:11:11')));
    echo time1
     
    將time1 / 60 秒,就變成分了。
     
    補充說明:
    shell 單括號運算符號:
    a=$(date);
    等同于:a=`date`;
     
    雙括號運算符:
    a=$((1+2));
    echo $a;
    等同于:
    a=`expr 1 + 2`
    posted @ 2017-07-06 16:33 xzc 閱讀(3339) | 評論 (1)編輯 收藏
    僅列出標題
    共32頁: 上一頁 1 2 3 4 5 6 7 8 9 下一頁 Last 
    主站蜘蛛池模板: 中国亚洲呦女专区| 国产黄色免费观看| 精品女同一区二区三区免费播放| 精品国产日韩亚洲一区91| 永久免费无码日韩视频| 亚洲精品无码MV在线观看| 亚洲成年轻人电影网站www| 亚洲人成毛片线播放| 一级毛片a免费播放王色电影| 国产成人精品免费久久久久| 好男人www免费高清视频在线| 亚洲 小说区 图片区 都市| 亚洲一区二区中文| 特级aa**毛片免费观看| 131美女爱做免费毛片| 亚洲AV日韩精品一区二区三区| 亚洲AV午夜成人影院老师机影院| 亚洲人成黄网在线观看| 一区二区三区免费电影| 99无码人妻一区二区三区免费| 少妇亚洲免费精品| 亚洲另类视频在线观看| a级毛片免费网站| 岛国片在线免费观看| 亚洲AV乱码久久精品蜜桃| 另类专区另类专区亚洲| 亚洲免费在线观看视频| 亚洲一区无码精品色| 亚洲乱妇熟女爽到高潮的片| 四虎影视在线影院在线观看免费视频 | 久久精品私人影院免费看| 女人张开腿给人桶免费视频 | 亚洲国产高清视频| 成人免费夜片在线观看| 在人线av无码免费高潮喷水| 亚洲无人区一区二区三区| 亚洲av无码一区二区三区在线播放| 99re6在线视频精品免费下载| 精品国产亚洲男女在线线电影 | 999在线视频精品免费播放观看| 亚洲国产精品一区二区第一页|