Cassandra System.OutOfMemoryException, это ошибка Thrift? - PullRequest
4 голосов
/ 19 октября 2011

Я использую Cassandra 0.8.7, Aquiles в качестве клиента C # и Thrift 0.7, и я пытаюсь получить довольно большой объем данных из SuperColumnFamily со следующим определением:

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

IЯ хочу вставить данные, извлеченные из Cassandra, в DataTable, чтобы я мог отфильтровать строки и сгенерировать некоторые отчеты, основанные на этом, но я всегда получаю исключение OutOfMemoryException.Оптимизировав мой код, моя окончательная версия состояла в том, чтобы разделить период времени (и количество ключей, если они превышают префиксное число), которые я использую, чтобы разделить 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());
}

И это функция, которая должна вставлять данные из Кассандры в DataTable:

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: Проблема решена, прочитайте мой ответ ниже

Ответы [ 2 ]

1 голос
/ 25 октября 2011

Проблема решена :) Я поигрался с использованием памяти и сборщиком мусора и исправил проблему.

Случилось так, что когда мое приложение достигало 1,5 ГБ ОЗУ, возникало исключение из-за того, что визуальныйСтудия скомпилировала его как 32-битное приложение.

Компиляция и запуск, поскольку x64 решил проблему, чтобы не использовать слишком много памяти, теперь я добавил следующие 3 строки кода перед каждым вызовом Cassandra multiget_slice.

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

Спасибо, Н.

0 голосов
/ 19 октября 2011

Насколько велики данные в вашей семействе SuperColumn?По умолчанию Thrift имеет максимальный размер кадра 15 Мб.Это установлено в /etc/cassandra/conf/cassandra.yaml - вы можете попытаться увеличить это?

Обратите внимание, что невозможно разделить ваши данные меньше, чем один суперколонка.

...