
2017年5月12日
原文鏈接:http://www.cnblogs.com/juandx/p/4962089.html
python中對文件、文件夾(文件操作函數)的操作需要涉及到os模塊和shutil模塊。
得到當前工作目錄,即當前Python腳本工作的目錄路徑: os.getcwd()
返回指定目錄下的所有文件和目錄名:os.listdir()
函數用來刪除一個文件:os.remove()
刪除多個目錄:os.removedirs(r“c:\python”)
檢驗給出的路徑是否是一個文件:os.path.isfile()
檢驗給出的路徑是否是一個目錄:os.path.isdir()
判斷是否是絕對路徑:os.path.isabs()
檢驗給出的路徑是否真地存:os.path.exists()
返回一個路徑的目錄名和文件名:os.path.split()
eg os.path.split(‘/home/swaroop/byte/code/poem.txt’)
結果:(‘/home/swaroop/byte/code’, ‘poem.txt’)
分離擴展名:os.path.splitext()
獲取路徑名:os.path.dirname()
獲取文件名:os.path.basename()
運行shell命令: os.system()
讀取和設置環境變量:os.getenv() 與os.putenv()
給出當前平臺使用的行終止符:os.linesep Windows使用’\r\n’,Linux使用’\n’而Mac使用’\r’
指示你正在使用的平臺:os.name 對于Windows,它是’nt’,而對于Linux/Unix用戶,它是’posix’
重命名:os.rename(old, new)
創建多級目錄:os.makedirs(r“c:\python\test”)
創建單個目錄:os.mkdir(“test”)
獲取文件屬性:os.stat(file)
修改文件權限與時間戳:os.chmod(file)
終止當前進程:os.exit()
獲取文件大小:os.path.getsize(filename)
文件操作:
os.mknod(“test.txt”) 創建空文件
fp = open(“test.txt”,w) 直接打開一個文件,如果文件不存在則創建文件
關于open 模式:
w 以寫方式打開,
a 以追加模式打開 (從 EOF 開始, 必要時創建新文件)
r+ 以讀寫模式打開
w+ 以讀寫模式打開 (參見 w )
a+ 以讀寫模式打開 (參見 a )
rb 以二進制讀模式打開
wb 以二進制寫模式打開 (參見 w )
ab 以二進制追加模式打開 (參見 a )
rb+ 以二進制讀寫模式打開 (參見 r+ )
wb+ 以二進制讀寫模式打開 (參見 w+ )
ab+ 以二進制讀寫模式打開 (參見 a+ )
fp.read([size]) #size為讀取的長度,以byte為單位
fp.readline([size]) #讀一行,如果定義了size,有可能返回的只是一行的一部分
fp.readlines([size]) #把文件每一行作為一個list的一個成員,并返回這個list。其實它的內部是通過循環調用readline()來實現的。如果提供size參數,size是表示讀取內容的總長,也就是說可能只讀到文件的一部分。
fp.write(str) #把str寫到文件中,write()并不會在str后加上一個換行符
fp.writelines(seq) #把seq的內容全部寫到文件中(多行一次性寫入)。這個函數也只是忠實地寫入,不會在每行后面加上任何東西。
fp.close() #關閉文件。python會在一個文件不用后自動關閉文件,不過這一功能沒有保證,最好還是養成自己關閉的習慣。 如果一個文件在關閉后還對其進行操作會產生ValueError
fp.flush() #把緩沖區的內容寫入硬盤
fp.fileno() #返回一個長整型的”文件標簽“
fp.isatty() #文件是否是一個終端設備文件(unix系統中的)
fp.tell() #返回文件操作標記的當前位置,以文件的開頭為原點
fp.next() #返回下一行,并將文件操作標記位移到下一行。把一個file用于for … in file這樣的語句時,就是調用next()函數來實現遍歷的。
fp.seek(offset[,whence]) #將文件打操作標記移到offset的位置。這個offset一般是相對于文件的開頭來計算的,一般為正數。但如果提供了whence參數就不一定了,whence可以為0表示從頭開始計算,1表示以當前位置為原點計算。2表示以文件末尾為原點進行計算。需要注意,如果文件以a或a+的模式打開,每次進行寫操作時,文件操作標記會自動返回到文件末尾。
fp.truncate([size]) #把文件裁成規定的大小,默認的是裁到當前文件操作標記的位置。如果size比文件的大小還要大,依據系統的不同可能是不改變文件,也可能是用0把文件補到相應的大小,也可能是以一些隨機的內容加上去。
目錄操作:
os.mkdir(“file”) 創建目錄
復制文件:
shutil.copyfile(“oldfile”,”newfile”) oldfile和newfile都只能是文件
shutil.copy(“oldfile”,”newfile”) oldfile只能是文件夾,newfile可以是文件,也可以是目標目錄
復制文件夾:
shutil.copytree(“olddir”,”newdir”) olddir和newdir都只能是目錄,且newdir必須不存在
重命名文件(目錄)
os.rename(“oldname”,”newname”) 文件或目錄都是使用這條命令
移動文件(目錄)
shutil.move(“oldpos”,”newpos”)
刪除文件
os.remove(“file”)
刪除目錄
os.rmdir(“dir”)只能刪除空目錄
shutil.rmtree(“dir”) 空目錄、有內容的目錄都可以刪
轉換目錄
os.chdir(“path”) 換路徑
Python讀寫文件
1.open
使用open打開文件后一定要記得調用文件對象的close()方法。比如可以用try/finally語句來確保最后能關閉文件。
file_object = open(‘thefile.txt’)
try:
all_the_text = file_object.read( )
finally:
file_object.close( )
注:不能把open語句放在try塊里,因為當打開文件出現異常時,文件對象file_object無法執行close()方法。
2.讀文件
讀文本文件
input = open('data', 'r')
#第二個參數默認為r
input = open('data')
1
2
3
讀二進制文件
input = open('data', 'rb')
1
讀取所有內容
file_object = open('thefile.txt')
try:
all_the_text = file_object.read( )
finally:
file_object.close( )
1
2
3
4
5
讀固定字節
file_object = open('abinfile', 'rb')
try:
while True:
chunk = file_object.read(100)
if not chunk:
break
do_something_with(chunk)
finally:
file_object.close( )
1
2
3
4
5
6
7
8
9
讀每行
list_of_all_the_lines = file_object.readlines( )
1
如果文件是文本文件,還可以直接遍歷文件對象獲取每行:
for line in file_object:
process line
1
2
3.寫文件
寫文本文件
output = open('data', 'w')
1
寫二進制文件
output = open('data', 'wb')
1
追加寫文件
output = open('data', 'w+')
1
寫數據
file_object = open('thefile.txt', 'w')
file_object.write(all_the_text)
file_object.close( )
1
2
3
寫入多行
file_object.writelines(list_of_text_strings)
1
注意,調用writelines寫入多行在性能上會比使用write一次性寫入要高。
在處理日志文件的時候,常常會遇到這樣的情況:日志文件巨大,不可能一次性把整個文件讀入到內存中進行處理,例如需要在一臺物理內存為 2GB 的機器上處理一個 2GB 的日志文件,我們可能希望每次只處理其中 200MB 的內容。
在 Python 中,內置的 File 對象直接提供了一個 readlines(sizehint) 函數來完成這樣的事情。以下面的代碼為例:
file = open('test.log', 'r')sizehint = 209715200 # 200Mposition = 0lines = file.readlines(sizehint)while not file.tell() - position < 0: position = file.tell() lines = file.readlines(sizehint)
1
每次調用 readlines(sizehint) 函數,會返回大約 200MB 的數據,而且所返回的必然都是完整的行數據,大多數情況下,返回的數據的字節數會稍微比 sizehint 指定的值大一點(除最后一次調用 readlines(sizehint) 函數的時候)。通常情況下,Python 會自動將用戶指定的 sizehint 的值調整成內部緩存大小的整數倍。
file在python是一個特殊的類型,它用于在python程序中對外部的文件進行操作。在python中一切都是對象,file也不例外,file有file的方法和屬性。下面先來看如何創建一個file對象:
file(name[, mode[, buffering]])
1
file()函數用于創建一個file對象,它有一個別名叫open(),可能更形象一些,它們是內置函數。來看看它的參數。它參數都是以字符串的形式傳遞的。name是文件的名字。
mode是打開的模式,可選的值為r w a U,分別代表讀(默認) 寫 添加支持各種換行符的模式。用w或a模式打開文件的話,如果文件不存在,那么就自動創建。此外,用w模式打開一個已經存在的文件時,原有文件的內容會被清空,因為一開始文件的操作的標記是在文件的開頭的,這時候進行寫操作,無疑會把原有的內容給抹掉。由于歷史的原因,換行符在不同的系統中有不同模式,比如在 unix中是一個\n,而在windows中是‘\r\n’,用U模式打開文件,就是支持所有的換行模式,也就說‘\r’ ‘\n’ ‘\r\n’都可表示換行,會有一個tuple用來存貯這個文件中用到過的換行符。不過,雖說換行有多種模式,讀到python中統一用\n代替。在模式字符的后面,還可以加上+ b t這兩種標識,分別表示可以對文件同時進行讀寫操作和用二進制模式、文本模式(默認)打開文件。
buffering如果為0表示不進行緩沖;如果為1表示進行“行緩沖“;如果是一個大于1的數表示緩沖區的大小,應該是以字節為單位的。
file對象有自己的屬性和方法。先來看看file的屬性。
closed #標記文件是否已經關閉,由close()改寫
encoding #文件編碼
mode #打開模式
name #文件名
newlines #文件中用到的換行模式,是一個tuple
softspace #boolean型,一般為0,據說用于print
1
2
3
4
5
6
file的讀寫方法:
F.read([size]) #size為讀取的長度,以byte為單位
F.readline([size])
#讀一行,如果定義了size,有可能返回的只是一行的一部分
F.readlines([size])
#把文件每一行作為一個list的一個成員,并返回這個list。其實它的內部是通過循環調用readline()來實現的。如果提供size參數,size是表示讀取內容的總長,也就是說可能只讀到文件的一部分。
F.write(str)
#把str寫到文件中,write()并不會在str后加上一個換行符
F.writelines(seq)
#把seq的內容全部寫到文件中。這個函數也只是忠實地寫入,不會在每行后面加上任何東西。
file的其他方法:
F.close()
#關閉文件。python會在一個文件不用后自動關閉文件,不過這一功能沒有保證,最好還是養成自己關閉的習慣。如果一個文件在關閉后還對其進行操作會產生ValueError
F.flush()
#把緩沖區的內容寫入硬盤
F.fileno()
#返回一個長整型的”文件標簽“
F.isatty()
#文件是否是一個終端設備文件(unix系統中的)
F.tell()
#返回文件操作標記的當前位置,以文件的開頭為原點
F.next()
#返回下一行,并將文件操作標記位移到下一行。把一個file用于for ... in file這樣的語句時,就是調用next()函數來實現遍歷的。
F.seek(offset[,whence])
#將文件打操作標記移到offset的位置。這個offset一般是相對于文件的開頭來計算的,一般為正數。但如果提供了whence參數就不一定了,whence可以為0表示從頭開始計算,1表示以當前位置為原點計算。2表示以文件末尾為原點進行計算。需要注意,如果文件以a或a+的模式打開,每次進行寫操作時,文件操作標記會自動返回到文件末尾。
F.truncate([size])
#把文件裁成規定的大小,默認的是裁到當前文件操作標記的位置。如果size比文件的大小還要大,依據系統的不同可能是不改變文件,也可能是用0把文件補到相應的大小,也可能是以一些隨機的內容加上去。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
http://www.cnblogs.com/allenblogs/archive/2010/09/13/1824842.html
http://www.cnblogs.com/rollenholt/archive/2012/04/23/2466179.html
posted @
2018-11-28 11:52 xzc 閱讀(557) |
評論 (0) |
編輯 收藏
首先 dfs.replication這個參數是個client參數,即node level參數。需要在每臺datanode上設置。
其實默認為3個副本已經夠用了,設置太多也沒什么用。
一個文件,上傳到hdfs上時指定的是幾個副本就是幾個。以后你修改了副本數,對已經上傳了的文件也不會起作用。可以再上傳文件的同時指定創建的副本數
Hadoop dfs -D dfs.replication=1 -put 70M logs/2
可以通過命令來更改已經上傳的文件的副本數:
hadoop fs -setrep -R 3 /
查看當前hdfs的副本數
hadoop fsck -locations
FSCK started by hadoop from /172.18.6.112 for path / at Thu Oct 27 13:24:25 CST 2011
....................Status: HEALTHY
Total size: 4834251860 B
Total dirs: 21
Total files: 20
Total blocks (validated): 82 (avg. block size 58954290 B)
Minimally replicated blocks: 82 (100.0 %)
Over-replicated blocks: 0 (0.0 %)
Under-replicated blocks: 0 (0.0 %)
Mis-replicated blocks: 0 (0.0 %)
Default replication factor: 3
Average block replication: 3.0
Corrupt blocks: 0
Missing replicas: 0 (0.0 %)
Number of data-nodes: 3
Number of racks: 1
FSCK ended at Thu Oct 27 13:24:25 CST 2011 in 10 milliseconds
The filesystem under path '/' is HEALTHY
某個文件的副本數,可以通過ls中的文件描述符看到
hadoop dfs -ls
-rw-r--r-- 3 hadoop supergroup 153748148 2011-10-27 16:11 /user/hadoop/logs/201108/impression_witspixel2011080100.thin.log.gz
如果你只有3個datanode,但是你卻指定副本數為4,是不會生效的,因為每個datanode上只能存放一個副本。
參考:http://blog.csdn.net/lskyne/article/details/8898666
posted @
2018-11-26 11:52 xzc 閱讀(874) |
評論 (0) |
編輯 收藏
轉自:https://www.cnblogs.com/shabbylee/p/6792555.html
由于歷史原因,Python有兩個大的版本分支,Python2和Python3,又由于一些庫只支持某個版本分支,所以需要在電腦上同時安裝Python2和Python3,因此如何讓兩個版本的Python兼容,如何讓腳本在對應的Python版本上運行,這個是值得總結的。
對于Ubuntu 16.04 LTS版本來說,Python2(2.7.12)和Python3(3.5.2)默認同時安裝,默認的python版本是2.7.12。
當然你也可以用python2來調用。
如果想調用python3,就用python3.
對于Windows,就有點復雜了。因為不論python2還是python3,python可執行文件都叫python.exe,在cmd下輸入python得到的版本號取決于環境變量里哪個版本的python路徑更靠前,畢竟windows是按照順序查找的。比如環境變量里的順序是這樣的:
那么cmd下的python版本就是2.7.12。
反之,則是python3的版本號。
這就帶來一個問題了,如果你想用python2運行一個腳本,一會你又想用python3運行另一個腳本,你怎么做?來回改環境變量顯然很麻煩。
網上很多辦法比較簡單粗暴,把兩個python.exe改名啊,一個改成python2.exe,一個改成python3.exe。這樣做固然可以,但修改可執行文件的方式,畢竟不是很好的方法。
我仔細查找了一些python技術文檔,發現另外一個我覺得比較好的解決辦法。
借用py的一個參數來調用不同版本的Python。py -2調用python2,py -3調用的是python3.
當python腳本需要python2運行時,只需在腳本前加上,然后運行py xxx.py即可。
#! python2
當python腳本需要python3運行時,只需在腳本前加上,,然后運行py xxx.py即可。
#! python3
就這么簡單。
同時,這也完美解決了在pip在python2和python3共存的環境下報錯,提示Fatal error in launcher: Unable to create process using '"'的問題。
當需要python2的pip時,只需
py -2 -m pip install xxx
當需要python3的pip時,只需
py -3 -m pip install xxx
python2和python3的pip package就這樣可以完美分開了。
posted @
2018-11-16 09:38 xzc 閱讀(632) |
評論 (0) |
編輯 收藏
Sentry權限控制通過Beeline(Hiveserver2 SQL 命令行接口)輸入Grant 和 Revoke語句來配置。語法跟現在的一些主流的關系數據庫很相似。需要注意的是:當sentry服務啟用后,我們必須使用beeline接口來執行hive查詢,Hive Cli并不支持sentry。
CREATE ROLE Statement
CREATE ROLE語句創建一個可以被賦權的角色。權限可以賦給角色,然后再分配給各個用戶。一個用戶被分配到角色后可以執行該角色的權限。
只有擁有管理員的角色可以create/drop角色。默認情況下,hive、impala和hue用戶擁有管理員角色。
CREATE ROLE [role_name];
DROP ROLE Statement
DROP ROLE語句可以用來從數據庫中移除一個角色。一旦移除,之前分配給所有用戶的該角色將會取消。之前已經執行的語句不會受到影響。但是,因為hive在執行每條查詢語句之前會檢查用戶的權限,處于登錄活躍狀態的用戶會話會受到影響。
DROP ROLE [role_name];
GRANT ROLE Statement
GRANT ROLE語句可以用來給組授予角色。只有sentry的管理員用戶才能執行該操作。
GRANT ROLE role_name [, role_name]
TO GROUP (groupName) [,GROUP (groupName)]
REVOKE ROLE Statement
REVOKE ROLE語句可以用來從組移除角色。只有sentry的管理員用戶才能執行該操作。
REVOKE ROLE role_name [, role_name]
FROM GROUP (groupName) [,GROUP (groupName)]
GRANT (PRIVILEGE) Statement
授予一個對象的權限給一個角色,該用戶必須為sentry的管理員用戶。
GRANT
(PRIVILEGE) [, (PRIVILEGE) ]
ON (OBJECT) (object_name)
TO ROLE (roleName) [,ROLE (roleName)]
REVOKE (PRIVILEGE) Statement
因為只有認證的管理員用戶可以創建角色,從而只有管理員用戶可以取消一個組的權限。
REVOKE
(PRIVILEGE) [, (PRIVILEGE) ]
ON (OBJECT) (object_name)
FROM ROLE (roleName) [,ROLE (roleName)]
GRANT (PRIVILEGE) ... WITH GRANT OPTION
在cdh5.2中,你可以委托給其他角色來授予和解除權限。比如,一個角色被授予了WITH GRANT OPTION的權限可以GRANT/REVOKE同樣的權限給其他角色。因此,如果一個角色有一個庫的所有權限并且設置了 WITH GRANT OPTION,該角色分配的用戶可以對該數據庫和其中的表執行GRANT/REVOKE語句。
GRANT
(PRIVILEGE)
ON (OBJECT) (object_name)
TO ROLE (roleName)
WITH GRANT OPTION
只有一個帶GRANT選項的特殊權限的角色或者它的父級權限可以從其他角色解除這種權限。一旦下面的語句執行,所有跟其相關的grant權限將會被解除。
REVOKE
(RIVILEGE)
ON (BJECT) (bject_name)
FROM ROLE (roleName)
Hive目前不支持解除之前賦予一個角色 WITH GRANT OPTION 的權限。要想移除WITH GRANT OPTION、解除權限,可以重新去除 WITH GRANT OPTION這個標記來再次附權。
SET ROLE Statement
SET ROLE語句可以給當前會話選擇一個角色使之生效。一個用戶只能啟用分配給他的角色。任何不存在的角色和當前用戶不能使用的角色是不能生效的。如果沒有使用任何角色,用戶將會使用任何一個屬于他的角色的權限。
選擇一個角色使用:
To enable a specific role:
使用所有的角色:
To enable a specific role:
關閉所有角色
SET ROLE NONE;
SHOW Statement
顯示當前用戶擁有庫、表、列相關權限的數據庫:
SHOW DATABASES;
顯示當前用戶擁有表、列相關權限的表;
SHOW TABLES;
顯示當前用戶擁有SELECT權限的列:
SHOW COLUMNS (FROM|IN) table_name [(FROM|IN) db_name];
顯示當前系統中所有的角色(只有管理員用戶可以執行):
SHOW ROLES;
顯示當前影響當前會話的角色:
SHOW CURRENT ROLES;
顯示指定組的被分配到的所有角色(只有管理員用戶和指定組內的用戶可以執行)
SHOW ROLE GRANT GROUP (groupName);
SHOW語句可以用來顯示一個角色被授予的權限或者顯示角色的一個特定對象的所有權限。
顯示指定角色的所有被賦予的權限。(只有管理員用戶和指定角色分配到的用戶可以執行)。下面的語句也會顯示任何列級的權限。
SHOW GRANT ROLE (roleName);
顯示指定對象的一個角色的所有被賦予的權限(只有管理員用戶和指定角色分配到的用戶可以執行)。下面的語句也會顯示任何列級的權限。
SHOW GRANT ROLE (roleName) on (OBJECT) (objectName);
----------------------------我也是有底線的-----------------------------
posted @
2018-09-03 18:19 xzc 閱讀(499) |
評論 (0) |
編輯 收藏
摘要: Python 里面的編碼和解碼也就是 unicode 和 str 這兩種形式的相互轉化。編碼是 unicode -> str,相反的,解碼就是 str -> unicode。剩下的問題就是確定何時需要進行編碼或者解碼了.關于文件開頭的"編碼指示",也就是 # -*- codin...
閱讀全文
posted @
2018-05-18 09:52 xzc 閱讀(411) |
評論 (0) |
編輯 收藏
一、前言
早上醒來打開微信,同事反饋kafka集群從昨天凌晨開始寫入頻繁失敗,趕緊打開電腦查看了kafka集群的機器監控,日志信息,發現其中一個節點的集群負載從昨天凌晨突然掉下來了,和同事反饋的時間點大概一致,于是乎就登錄服務器開始干活。
二、排錯
1、查看機器監控,看是否能大概定位是哪個節點有異常
技術分享
2、根據機器監控大概定位到其中一個異常節點,登錄服務器查看kafka日志,發現有報錯日志,并且日志就停留在這個這個時間點:
[2017-06-01 16:59:59,851] ERROR Processor got uncaught exception. (kafka.network.Processor)
java.lang.OutOfMemoryError: Direct buffer memory
at java.nio.Bits.reserveMemory(Bits.java:658)
at java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:123)
at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:306)
at sun.nio.ch.Util.getTemporaryDirectBuffer(Util.java:174)
at sun.nio.ch.IOUtil.read(IOUtil.java:195)
at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:379)
at org.apache.kafka.common.network.PlaintextTransportLayer.read(PlaintextTransportLayer.java:108)
at org.apache.kafka.common.network.NetworkReceive.readFromReadableChannel(NetworkReceive.java:97)
at org.apache.kafka.common.network.NetworkReceive.readFrom(NetworkReceive.java:71)
at org.apache.kafka.common.network.KafkaChannel.receive(KafkaChannel.java:160)
at org.apache.kafka.common.network.KafkaChannel.read(KafkaChannel.java:141)
at org.apache.kafka.common.network.Selector.poll(Selector.java:286)
at kafka.network.Processor.run(SocketServer.scala:413)3、查看kafka進程和監聽端口情況,發現都正常,尼瑪假死了
ps -ef |grep kafka ## 查看kafka的進程
netstat -ntlp |grep 9092 ##9092kafka的監聽端口4、既然已經假死了,只能重啟了
ps -ef |grep kafka |grep -v grep |awk ‘{print $2}‘ | xargs kill -9
/usr/local/kafka/bin;nohup ./kafka-server-start.sh ../config/server.properties &5、重啟后在觀察該節點的kafka日志,在一頓index重建之后,上面的報錯信息在瘋狂的刷,最后谷歌一番,解決了該問題
三、解決方案:
在
/usr/local/kafka/binkafka-run-class.sh去掉
-XX:+DisableExplicitGC添加
-XX:MaxDirectMemorySize=512m在一次重啟kafka,問題解決。
posted @
2018-03-08 16:35 xzc 閱讀(2177) |
評論 (0) |
編輯 收藏
摘要: 我們每次執行hive的hql時,shell里都會提示一段話:[python] view plaincopy... Number of reduce tasks not specified. Estimated from input data size: 50...
閱讀全文
posted @
2018-03-07 11:21 xzc 閱讀(1516) |
評論 (1) |
編輯 收藏
摘要: spark 累加歷史主要用到了窗口函數,而進行全部統計,則需要用到rollup函數
1 應用場景:
1、我們需要統計用戶的總使用時長(累加歷史)
2、前臺展現頁面需要對多個維度進行查詢,如:產品、地區等等
3、需要展現的表格頭如: 產品、2015-04、2015-05、2015-06
2 原始數據:
product_code |event_date |dur...
閱讀全文
posted @
2017-10-23 22:05 xzc 閱讀(875) |
評論 (0) |
編輯 收藏
摘要: Spark1.4發布,支持了窗口分析函數(window functions)。在離線平臺中,90%以上的離線分析任務都是使用Hive實現,其中必然會使用很多窗口分析函數,如果SparkSQL支持窗口分析函數,
那么對于后面Hive向SparkSQL中的遷移的工作量會大大降低,使用方式如下:
1、初始化數據
創建表
[sql] view plain cop...
閱讀全文
posted @
2017-10-23 22:04 xzc 閱讀(695) |
評論 (0) |
編輯 收藏
1.in 不支持子查詢 eg. select * from src where key in(select key from test);
支持查詢個數 eg. select * from src where key in(1,2,3,4,5);
in 40000個 耗時25.766秒
in 80000個 耗時78.827秒
2.union all/union
不支持頂層的union all eg. select key from src UNION ALL select key from test;
支持select * from (select key from src union all select key from test)aa;
不支持 union
支持select distinct key from (select key from src union all select key from test)aa;
3.intersect 不支持
4.minus 不支持
5.except 不支持
6.inner join/join/left outer join/right outer join/full outer join/left semi join 都支持
left outer join/right outer join/full outer join 中間必須有outer
join是最簡單的關聯操作,兩邊關聯只取交集;
left outer join是以左表驅動,右表不存在的key均賦值為null;
right outer join是以右表驅動,左表不存在的key均賦值為null;
full outer join全表關聯,將兩表完整的進行笛卡爾積操作,左右表均可賦值為null;
left semi join最主要的使用場景就是解決exist in;
Hive不支持where子句中的子查詢,SQL常用的exist in子句在Hive中是不支持的
不支持子查詢 eg. select * from src aa where aa.key in(select bb.key from test bb);
可用以下兩種方式替換:
select * from src aa left outer join test bb on aa.key=bb.key where bb.key <> null;
select * from src aa left semi join test bb on aa.key=bb.key;
大多數情況下 JOIN ON 和 left semi on 是對等的
A,B兩表連接,如果B表存在重復數據
當使用JOIN ON的時候,A,B表會關聯出兩條記錄,應為ON上的條件符合;
而是用LEFT SEMI JOIN 當A表中的記錄,在B表上產生符合條件之后就返回,不會再繼續查找B表記錄了,
所以如果B表有重復,也不會產生重復的多條記錄。
left outer join 支持子查詢 eg. select aa.* from src aa left outer join (select * from test111)bb on aa.key=bb.a;
7. hive四中數據導入方式
1)從本地文件系統中導入數據到Hive表
create table wyp(id int,name string) ROW FORMAT delimited fields terminated by '\t' STORED AS TEXTFILE;
load data local inpath 'wyp.txt' into table wyp;
2)從HDFS上導入數據到Hive表
[wyp@master /home/q/hadoop-2.2.0]$ bin/hadoop fs -cat /home/wyp/add.txt
hive> load data inpath '/home/wyp/add.txt' into table wyp;
3)從別的表中查詢出相應的數據并導入到Hive表中
hive> create table test(
> id int, name string
> ,tel string)
> partitioned by
> (age int)
> ROW FORMAT DELIMITED
> FIELDS TERMINATED BY '\t'
> STORED AS TEXTFILE;
注:test表里面用age作為了分區字段,分區:在Hive中,表的每一個分區對應表下的相應目錄,所有分區的數據都是存儲在對應的目錄中。
比如wyp表有dt和city兩個分區,則對應dt=20131218city=BJ對應表的目錄為/user/hive/warehouse/dt=20131218/city=BJ,
所有屬于這個分區的數據都存放在這個目錄中。
hive> insert into table test
> partition (age='25')
> select id, name, tel
> from wyp;
也可以在select語句里面通過使用分區值來動態指明分區:
hive> set hive.exec.dynamic.partition.mode=nonstrict;
hive> insert into table test
> partition (age)
> select id, name,
> tel, age
> from wyp;
Hive也支持insert overwrite方式來插入數據
hive> insert overwrite table test
> PARTITION (age)
> select id, name, tel, age
> from wyp;
Hive還支持多表插入
hive> from wyp
> insert into table test
> partition(age)
> select id, name, tel, age
> insert into table test3
> select id, name
> where age>25;
4)在創建表的時候通過從別的表中查詢出相應的記錄并插入到所創建的表中
hive> create table test4
> as
> select id, name, tel
> from wyp;
8.查看建表語句
hive> show create table test3;
9.表重命名
hive> ALTER TABLE events RENAME TO 3koobecaf;
10.表增加列
hive> ALTER TABLE pokes ADD COLUMNS (new_col INT);
11.添加一列并增加列字段注釋
hive> ALTER TABLE invites ADD COLUMNS (new_col2 INT COMMENT 'a comment');
12.刪除表
hive> DROP TABLE pokes;
13.top n
hive> select * from test order by key limit 10;
14.創建數據庫
Create Database baseball;
14.alter table tablename change oldColumn newColumn column_type 修改列的名稱和類型
alter table yangsy CHANGE product_no phone_no string
15.導入.sql文件中的sql
spark-sql --driver-class-path /home/hadoop/hive/lib/mysql-connector-java-5.1.30-bin.jar -f testsql.sql
insert into table CI_CUSER_20141117154351522 select mainResult.PRODUCT_NO,dw_coclbl_m02_3848.L1_01_02_01,dw_coclbl_d01_3845.L2_01_01_04 from (select PRODUCT_NO from CI_CUSER_20141114203632267) mainResult left join DW_COCLBL_M02_201407 dw_coclbl_m02_3848 on mainResult.PRODUCT_NO = dw_coclbl_m02_3848.PRODUCT_NO left join DW_COCLBL_D01_20140515 dw_coclbl_d01_3845 on dw_coclbl_m02_3848.PRODUCT_NO = dw_coclbl_d01_3845.PRODUCT_NO
insert into CI_CUSER_20141117142123638 ( PRODUCT_NO,ATTR_COL_0000,ATTR_COL_0001) select mainResult.PRODUCT_NO,dw_coclbl_m02_3848.L1_01_02_01,dw_coclbl_m02_3848.L1_01_03_01 from (select PRODUCT_NO from CI_CUSER_20141114203632267) mainResult left join DW_COCLBL_M02_201407 dw_coclbl_m02_3848 on mainResult.PRODUCT_NO = dw_coclbl_m02_3848.PRODUCT_NO
CREATE TABLE ci_cuser_yymmddhhmisstttttt_tmp(product_no string) row format serde 'com.bizo.hive.serde.csv.CSVSerde' ;
LOAD DATA LOCAL INPATH '/home/ocdc/coc/yuli/test123.csv' OVERWRITE INTO TABLE test_yuli2;
創建支持CSV格式的testfile文件
CREATE TABLE test_yuli7 row format serde 'com.bizo.hive.serde.csv.CSVSerde' as select * from CI_CUSER_20150310162729786;
不依賴CSVSerde的jar包創建逗號分隔的表
"create table " +listName+ " ROW FORMAT DELIMITED FIELDS TERMINATED BY ','" +
" as select * from " + listName1;
create table aaaa ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n' STORED AS TEXTFILE as select * from
ThriftServer 開啟FAIR模式
SparkSQL Thrift Server 開啟FAIR調度方式:
1. 修改$SPARK_HOME/conf/spark-defaults.conf,新增
2. spark.scheduler.mode FAIR
3. spark.scheduler.allocation.file /Users/tianyi/github/community/apache-spark/conf/fair-scheduler.xml
4. 修改$SPARK_HOME/conf/fair-scheduler.xml(或新增該文件), 編輯如下格式內容
5. <?xml version="1.0"?>
6. <allocations>
7. <pool name="production">
8. <schedulingMode>FAIR</schedulingMode>
9. <!-- weight表示兩個隊列在minShare相同的情況下,可以使用資源的比例 -->
10. <weight>1</weight>
11. <!-- minShare表示優先保證的資源數 -->
12. <minShare>2</minShare>
13. </pool>
14. <pool name="test">
15. <schedulingMode>FIFO</schedulingMode>
16. <weight>2</weight>
17. <minShare>3</minShare>
18. </pool>
19. </allocations>
20. 重啟Thrift Server
21. 執行SQL前,執行
22. set spark.sql.thriftserver.scheduler.pool=指定的隊列名
等操作完了 create table yangsy555 like CI_CUSER_YYMMDDHHMISSTTTTTT 然后insert into yangsy555 select * from yangsy555
創建一個自增序列表,使用row_number() over()為表增加序列號 以供分頁查詢
create table yagnsytest2 as SELECT ROW_NUMBER() OVER() as id,* from yangsytest;

Sparksql的解析與Hiveql的解析的執行流程:

posted @
2017-10-23 21:03 xzc 閱讀(739) |
評論 (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) |
編輯 收藏
可參照:http://www.voidcn.com/blog/Vindra/article/p-4917667.html
一、get請求
curl "http://www.baidu.com" 如果這里的URL指向的是一個文件或者一幅圖都可以直接下載到本地
curl -i "http://www.baidu.com" 顯示全部信息
curl -l "http://www.baidu.com" 只顯示頭部信息
curl -v "http://www.baidu.com" 顯示get請求全過程解析
wget "http://www.baidu.com"也可以
二、post請求
curl -d "param1=value1¶m2=value2" "http://www.baidu.com"
三、json格式的post請求
curl -l -H "Content-type: application/json" -X POST -d '{"phone":"13521389587","password":"test"}' http://domain/apis/users.json
例如:
curl -l -H "Content-type: application/json" -X POST -d '{"ver": "1.0","soa":{"req":"123"},"iface":"me.ele.lpdinfra.prediction.service.PredictionService","method":"restaurant_make_order_time","args":{"arg2":"\"stable\"","arg1":"{\"code\":[\"WIND\"],\"temperature\":11.11}","arg0":"{\"tracking_id\":\"100000000331770936\",\"eleme_order_id\":\"100000000331770936\",\"platform_id\":\"4\",\"restaurant_id\":\"482571\",\"dish_num\":1,\"dish_info\":[{\"entity_id\":142547763,\"quantity\":1,\"category_id\":1,\"dish_name\":\"[0xe7][0x89][0xb9][0xe4][0xbb][0xb7][0xe8][0x85][0x8a][0xe5][0x91][0xb3][0xe5][0x8f][0x89][0xe7][0x83][0xa7][0xe5][0x8f][0x8c][0xe6][0x8b][0xbc][0xe7][0x85][0xb2][0xe4][0xbb][0x94][0xe9][0xa5][0xad]\",\"price\":31.0}],\"merchant_location\":{\"longitude\":\"121.47831425\",\"latitude\":\"31.27576153\"},\"customer_location\":{\"longitude\":\"121.47831425\",\"latitude\":\"31.27576153\"},\"created_at\":1477896550,\"confirmed_at\":1477896550,\"dishes_total_price\":0.0,\"food_boxes_total_price\":2.0,\"delivery_total_price\":2.0,\"pay_amount\":35.0,\"city_id\":\"1\"}"}}' http://vpcb-lpdinfra-stream-1.vm.elenet.me:8989/rpc
ps:json串內層參數需要格式化
posted @
2017-05-18 11:28 xzc 閱讀(1646) |
評論 (1) |
編輯 收藏
服務器上的一些統計數據:
1)統計80端口連接數
netstat -nat|grep -i "80"|wc -l
2)統計httpd協議連接數
ps -ef|grep httpd|wc -l
3)、統計已連接上的,狀態為“established
netstat -na|grep ESTABLISHED|wc -l
4)、查出哪個IP地址連接最多,將其封了.
netstat -na|grep ESTABLISHED|awk {print $5}|awk -F: {print $1}|sort|uniq -c|sort -r +0n
netstat -na|grep SYN|awk {print $5}|awk -F: {print $1}|sort|uniq -c|sort -r +0n
---------------------------------------------------------------------------------------------
1、查看apache當前并發訪問數:
netstat -an | grep ESTABLISHED | wc -l
對比httpd.conf中MaxClients的數字差距多少。
2、查看有多少個進程數:
ps aux|grep httpd|wc -l
3、可以使用如下參數查看數據
server-status?auto
#ps -ef|grep httpd|wc -l
1388
統計httpd進程數,連個請求會啟動一個進程,使用于Apache服務器。
表示Apache能夠處理1388個并發請求,這個值Apache可根據負載情況自動調整。
#netstat -nat|grep -i "80"|wc -l
4341
netstat -an會打印系統當前網絡鏈接狀態,而grep -i "80"是用來提取與80端口有關的連接的,wc -l進行連接數統計。
最終返回的數字就是當前所有80端口的請求總數。
#netstat -na|grep ESTABLISHED|wc -l
376
netstat -an會打印系統當前網絡鏈接狀態,而grep ESTABLISHED 提取出已建立連接的信息。 然后wc -l統計。
最終返回的數字就是當前所有80端口的已建立連接的總數。
netstat -nat||grep ESTABLISHED|wc - 可查看所有建立連接的詳細記錄
查看Apache的并發請求數及其TCP連接狀態:
Linux命令:
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
返回結果示例:
LAST_ACK 5
SYN_RECV 30
ESTABLISHED 1597
FIN_WAIT1 51
FIN_WAIT2 504
TIME_WAIT 1057
其中的
SYN_RECV表示正在等待處理的請求數;
ESTABLISHED表示正常數據傳輸狀態;
TIME_WAIT表示處理完畢,等待超時結束的請求數。
---------------------------------------------------------------------------------------------
查看httpd進程數(即prefork模式下Apache能夠處理的并發請求數):
Linux命令:
ps -ef | grep httpd | wc -l
查看Apache的并發請求數及其TCP連接狀態:
Linux命令:
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
返回結果示例:
LAST_ACK 5
SYN_RECV 30
ESTABLISHED 1597
FIN_WAIT1 51
FIN_WAIT2 504
TIME_WAIT 1057
說明:
SYN_RECV表示正在等待處理的請求數;
ESTABLISHED表示正常數據傳輸狀態;
TIME_WAIT表示處理完畢,等待超時結束的請求數。
posted @
2017-05-17 23:12 xzc 閱讀(1470) |
評論 (2) |
編輯 收藏
一、回收站簡介:
在HDFS里,刪除文件時,不會真正的刪除,其實是放入回收站/trash,回收站里的文件可以快速恢復。
可以設置一個時間閥值,當回收站里文件的存放時間超過這個閥值或是回收站被清空時,文件才會被徹底刪除,并且釋放占用的數據塊。
二、實例:
Hadoop的回收站trash功能默認是關閉的,所以需要在core-site.xml中手動開啟。
1、修改core-site.xml,增加:
<property> <name>fs.trash.interval</name> <value>1440</value> <description>Number of minutes between trash checkpoints. If zero, the trash feature is disabled. </description> </property>
默認是0,單位是分鐘,這里設置為1天。
刪除數據rm后,會將數據move到當前文件夾下的.Trash目錄。
2、測試
1)、新建目錄input
hadoop/bin/hadoop fs -mkdir input
2)、上傳文件
root@master:/data/soft# hadoop/bin/hadoop fs -copyFromLocal /data/soft/file0* input
3)、刪除目錄input
[root@master data]# hadoop fs -rmr input Moved to trash: hdfs://master:9000/user/root/input
4)、查看當前目錄
[root@master data]# hadoop fs -ls Found 2 items drwxr-xr-x - root supergroup 0 2011-02-12 22:17 /user/root/.Trash
發現input刪除了,多了一個目錄.Trash
5)、恢復剛剛刪除的目錄
[root@master data]# hadoop fs -mv /user/root/.Trash/Current/user/root/input /user/root/input
6)、查看恢復的數據
[root@master data]# hadoop fs -ls input Found 2 items -rw-r--r-- 3 root supergroup 22 2011-02-12 17:40 /user/root/input/file01 -rw-r--r-- 3 root supergroup 28 2011-02-12 17:40 /user/root/input/file02
7)、刪除.Trash目錄(清理垃圾)
[root@master data]# hadoop fs -rmr .Trash Deleted hdfs://master:9000/user/root/.Trash
posted @
2017-05-12 11:20 xzc 閱讀(215) |
評論 (0) |
編輯 收藏