爲什麼Writable數據類型應該是可變的? 使用Text(vs String)作爲Map,Combine,Shuffle或Reduce流程中的鍵/值的數據類型有什麼優勢?爲什麼Writable數據類型應該是可變的?
感謝&問候, 拉賈
爲什麼Writable數據類型應該是可變的? 使用Text(vs String)作爲Map,Combine,Shuffle或Reduce流程中的鍵/值的數據類型有什麼優勢?爲什麼Writable數據類型應該是可變的?
感謝&問候, 拉賈
你不能選擇,這些數據類型必須是可變的。
原因是序列化機制。讓我們看看代碼:
// version 1.x MapRunner#run()
K1 key = input.createKey();
V1 value = input.createValue();
while (input.next(key, value)) {
// map pair to output
mapper.map(key, value, output, reporter);
...
所以我們重新使用同一個鍵/值對的實例。 爲什麼?當時我不知道設計決定,但我認爲這是減少垃圾對象的數量。請注意,Hadoop相當古老,當時垃圾收集器的效率不如現在,但即使在今天,如果您要映射數十億個對象並直接將其作爲垃圾丟棄,它在運行時會產生很大的差異。
您無法使Writable
類型真正不可變的真正原因是您無法將字段聲明爲final
。讓我們用IntWritable
一個簡單的例子:
public class IntWritable implements WritableComparable {
private int value;
public IntWritable() {}
public IntWritable(int value) { set(value); }
...
如果你會讓它不可變這肯定不會與序列化過程中工作了,因爲你需要定義value
決賽。這是行不通的,因爲鍵和值是在運行時通過反射實例化的。這需要一個默認構造函數,因此InputFormat
無法猜測填充最終數據字段所需的參數。因此,重用實例的整個概念顯然與不可變性的概念相矛盾。
但是,您應該問自己在Map/Reduce中不可變的鍵/值應該具有哪種好處。在Joshua Bloch的Effective Java第15項中,他指出不可變類更容易設計,實現和使用。他是對的,因爲Hadoop的減速是可變性最壞的例子:
void reduce(IntWritable key, Iterable<Text> values, Context context) ...
在迭代的每個值是指same
共享對象。因此,如果許多人將自己的價值觀念變爲正常收藏,並問自己爲什麼總是保持相同的價值觀,那麼他們會感到困惑。最後歸結爲性能的折衷(CPU和內存 - 想象單個密鑰的數十億個價值對象必須駐留在RAM中)與簡單性之間的關係。
簡而言之,原因Writable
不能是Immutable
是方法在Writable
。 Hadoop
反序列化實例以使用默認(無參數)構造函數創建實例並調用readFields
來解析值。由於構造中沒有賦值,因此對象必須是可變的。
謝謝約翰。它闡明瞭爲了參與序列化/反序列化過程,需要將數據類型變爲可變。 Hadoop在反序列化過程中創建(對象)實例的級別。每個任務運行一個對象?如果映射器是多線程的,是否可以創建多個對象來並行地從同一個InputSplit中讀取字段? – Raja
我相信這是每個任務運行一個。它創建一個實例,以便在反序列化之前執行Comparable查找。據我所知,Hadoop在單個JVM中沒有多線程映射器。如果這是不正確的,請讓我知道。 –
謝謝托馬斯。這就解釋了爲什麼可寫數據類型被設計爲可變的。你能否詳細說明你提供的Reduce例子。這是否意味着Reduce將始終只使用集合對象的一個實例,並且其值永遠不會被修改? – Raja
@Raja沒有集合對象,'Iterable'是磁盤上的數據的直接代理,它將被序列化並且不斷地只填充一個值對象。 –