2011-10-19 21 views
4

我使用卡桑德拉0.8.7,Aquiles爲C#的客戶端和節儉0.7,我試圖讓數據的一個比較大的量了SuperColumnFamily具有以下定義:Cassandra System.OutOfMemoryException,它是一個Thrift錯誤嗎?

create column family SCF with column_type=Super and comparator=TimeUUIDType and subcomparator=AsciiType; 

我想插入從Cassandra獲取的數據導入到DataTable中,這樣我就能夠過濾行並根據這些行生成一些報告,但是我總是得到一個OutOfMemoryException。

[OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.] 
    Thrift.Transport.TFramedTransport.ReadFrame() +191 
    Thrift.Transport.TFramedTransport.Read(Byte[] buf, Int32 off, Int32 len) +101 
    Thrift.Transport.TTransport.ReadAll(Byte[] buf, Int32 off, Int32 len) +76 
    Thrift.Protocol.TBinaryProtocol.ReadAll(Byte[] buf, Int32 off, Int32 len) +66 
    Thrift.Protocol.TBinaryProtocol.ReadI32() +47 
    Thrift.Protocol.TBinaryProtocol.ReadMessageBegin() +75 
    Apache.Cassandra.Client.recv_multiget_slice() in D:\apache-cassandra-0.8.0-beta2\interface\gen-csharp\Apache\Cassandra\Cassandra.cs:304 
    Apache.Cassandra.Client.multiget_slice(List`1 keys, ColumnParent column_parent, SlicePredicate predicate, ConsistencyLevel consistency_level) in D:\apache-cassandra-0.8.0-beta2\interface\gen-csharp\Apache\Cassandra\Cassandra.cs:286 

我嘗試了幾種方法來優化我的代碼,我的最終版本是我使用的切片在更小的範圍的SuperColumn(如果他們超過預設數量和按鍵的數量),以分裂的時間段,但什麼也沒有,最終我總是得到同樣的例外。

它可能是Thrift庫的錯誤嗎?當我得到的異常總是指向代碼裏面Thrift.Transport.TFramedTransport以下部分:

private void ReadFrame() 
     { 
      byte[] i32rd = new byte[header_size]; 
      transport.ReadAll(i32rd, 0, header_size); 
      int size = 
       ((i32rd[0] & 0xff) << 24) | 
       ((i32rd[1] & 0xff) << 16) | 
       ((i32rd[2] & 0xff) << 8) | 
       ((i32rd[3] & 0xff)); 

      byte[] buff = new byte[size]; //Here the exception is thrown 
      transport.ReadAll(buff, 0, size); 
      readBuffer = new MemoryStream(buff); 
     } 

以下是我試圖運行代碼:

string columnFamily = "SCF"; 
    ICluster cluster = AquilesHelper.RetrieveCluster(ConfigurationManager.AppSettings["CLUSTERNAME"].ToString()); 
    ColumnParent columnParent = new ColumnParent() 
     { 
      Column_family = columnFamily 
     }; 
    List<byte[]> keys = //Function that return the list of the key i want to query 

    SlicePredicate predicate = new SlicePredicate(); 
    foreach (DateTime[] dates in dateList) 
    { 
     from = GuidGenerator.GenerateTimeBasedGuid(dates[0]); 
     to = GuidGenerator.GenerateTimeBasedGuid(dates[1]); 
     predicate = new SlicePredicate() 
     { 
      Slice_range = new SliceRange() 
      { 


    Count = int.MaxValue, 
     Reversed = false, 
     Start = Aquiles.Helpers.Encoders.ByteEncoderHelper.UUIDEnconder.ToByteArray(from), 
     Finish = Aquiles.Helpers.Encoders.ByteEncoderHelper.UUIDEnconder.ToByteArray(to) 
     }, 
    }; 
    cluster.Execute(new ExecutionBlock(delegate(CassandraClient client) 
    { 
     int maxKeys = Convert.ToInt32(ConfigurationManager.AppSettings["maxKeys"]); 
     CassandraMethods.TableCreator(ref dt, columnParent, predicate, keys, client, maxKeys); 
     return null; 
    }), ConfigurationManager.AppSettings["KEYSPACE"].ToString()); 
} 

這是函數,應該從卡桑德拉插入數據到數據表中:

public static DataTable TableCreator(ref DataTable dt, ColumnParent columnParent, SlicePredicate predicate, List<byte[]> keys, CassandraClient client, int maxKeys) 
{ 
    int keyCount = keys.Count; 
    if (keyCount < maxKeys) 
     CassandraMethods.CassandraToDataTable(ref dt, client.multiget_slice(keys, columnParent, predicate, ConsistencyLevel.ONE)); 
    else 
    { 
     int counter = 0; 
     while (counter < keyCount) 
     { 
     if (counter + maxKeys <= keyCount) 
      CassandraMethods.CassandraToDataTable(ref dt, client.multiget_slice(keys.GetRange(counter, maxKeys), columnParent, predicate, ConsistencyLevel.ONE)); 
     else 
      CassandraMethods.CassandraToDataTable(ref dt, client.multiget_slice(keys.GetRange(counter, keyCount - counter), columnParent, predicate, ConsistencyLevel.ONE)); 
     counter += maxKeys; 
     } 
    } 
    return dt; 
} 

我錯過了什麼嗎?我究竟做錯了什麼?

更新1:我也嘗試過Cassandra 1.0,Aquiles 1.0,Thrift 0.6和0.7兩個版本,但沒有任何異常。

更新2:問題解決了,請閱讀下面

回答

1

問題解決:) 我玩過內存使用和垃圾收集器,我解決了這個問題。

發生了什麼事情是,當我的應用程序達到1.5 GB的RAM時,由於Visual Studio將其編譯爲32位應用程序而引發異常。

作爲x64編譯和運行解決了發佈,以確保不會使用太多的內存,現在我在每個Cassandra multiget_slice調用之前添加了以下3行代碼。

GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced); 
GC.WaitForPendingFinalizers(); 
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced); 

感謝,N.

0

有多大你SuperColumnFamily數據我的答案?節儉的默認最大幀大小爲15 Mb。這設置在/etc/cassandra/conf/cassandra.yaml - 你可以嘗試增加這個?

請注意,不可能將數據拆分爲比單個超列更小的數據。

+0

我已經試圖增加該參數。我不認爲這是數據大小的問題,如果是這樣的話,當我查詢一個太大的行時,我總是會得到異常。例如,如果我在2011-01-01至2011-03-31之間查詢,可能會發生這樣的情況:我得到例外可以說2月28日;如果這是一個大數據的問題,我應該總是在2月28日例外的情況下得到例外嗎?相反,如果我開始我的切片那一天一切順利一段時間,我會在稍後得到異常。 – kefer9

相關問題