2016-04-07 46 views
4

我有一大堆對象,我需要稍後存儲和檢索。該列表將始終用作單元,列表項不會單獨檢索。該列表包含約7000條總計大約1GB的內容,但可以輕鬆升級至十倍或更多。使用C#序列化一個非常大的項目列表到Azure blob存儲中使用C#

我們一直在使用BinaryFormatter.Serialize()做序列化(System.Runtime.Serialization.Formatters.Binary.BinaryFormatter)。然後,該字符串作爲一個blob上傳到Azure blob存儲。我們發現它通常是快速和高效的,但是它變得不夠充分,因爲我們正在用更大的文件大小來測試它,並拋出OutOfMemoryException。據我所知,雖然我使用流,但我的問題是,BinaryFormatter.Serialize()方法必須先將所有內容序列化到內存中,然後才能上傳blob,導致我的異常。

的二進制序列如下所示:在formatter.Serialize(stream, value)線上發生

public void Upload(object value, string blobName, bool replaceExisting) 
{ 
    CloudBlockBlob blockBlob = BlobContainer.GetBlockBlobReference(blobName); 
    var formatter = new BinaryFormatter() 
    { 
     AssemblyFormat = FormatterAssemblyStyle.Simple, 
     FilterLevel = TypeFilterLevel.Low, 
     TypeFormat = FormatterTypeStyle.TypesAlways 
    }; 

    using (var stream = blockBlob.OpenWrite()) 
    { 
     formatter.Serialize(stream, value); 
    } 
} 

的OutOfMemoryException異常。

因此,我試圖使用不同的協議,協議緩衝區。我嘗試在Nuget包protobuf-net和Google.Protobuf中使用這兩種實現,但序列化速度非常慢(大約30分鐘),從我讀過的內容來看,Protobuf沒有針對大於1MB的數據進行序列化優化。於是,我回到了繪圖板,並遇到了Cap'n Proto,它承諾通過使用內存映射來解決我的速度問題。我正在嘗試使用@ marc-gravell的C#綁定,但由於該項目還沒有全面的文檔,因此在實現序列化程序時遇到了一些困難。此外,我並不十分確定Cap'n Proto是協議的正確選擇 - 但我正在努力在網上找到其他建議。

如何將一大批項目序列化到blob存儲,而不會遇到內存問題,並且以相當快的方式?

+0

上傳批次工作超過一個斑點,而不是一次序列化的一切嗎? – spender

+0

謝謝,這是我正在考慮的選項。每個列表在我們的域中已經是一個塊,儘管如此,blob會在某種程度上丟失上下文,這會讓事情變得複雜一點。好的建議,但如果沒有任何其他協議或方法的建議,我會給它一個鏡頭。 – Ivan

回答

0

也許你應該切換到JSON?

使用JSON串行器,您可以流入和流出文件,並逐段(當文件被讀取時)序列化/反序列化。

您的對象會映射到JSON嗎?

這是我用來採取NetworkStream並放入一個Json對象。

private static async Task<JObject> ProcessJsonResponse(HttpResponseMessage response) 
    { 
     // Open the stream the stream from the network 
     using (var s = await ProcessResponseStream(response).ConfigureAwait(false)) 
     { 
      using (var sr = new StreamReader(s)) 
      { 
       using (var reader = new JsonTextReader(sr)) 
       { 
        var serializer = new JsonSerializer {DateParseHandling = DateParseHandling.None}; 

        return serializer.Deserialize<JObject>(reader); 
       } 
      } 
     } 
    } 

此外,您可以GZip流來減少文件傳輸時間。我們直接將流式傳輸到GZipped JSON,然後再返回。

編輯,雖然這是一個反序列化,同樣的方法應該爲序列化