2017-08-03 77 views
1

從升級後出現錯誤「衝突類型ID [type1 ='行',type2 ='行',typeId = 113114]」 Apache Ignite 2.0至2.1(.Net)。升級後我沒有更改任何代碼,所以想知道如何創建和使用動態二進制對象的期望改變了?我看着AddType方法。也許它應該返回而不是拋出,也許該方法的名稱是誤導性的,它應該是GetOrAddType?Apache Ignite 2.1:從2.0升級後出現「衝突類型ID」錯誤

將AddType方法: https://github.com/apache/ignite/blob/efd299f401ea34e040037c76be0c9f86e0e8e239/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs#L667

堆棧跟蹤:

at Apache.Ignite.Core.Impl.Binary.Marshaller.ThrowConflictingTypeError(Object type1, Object type2, Int32 typeId) 
    at Apache.Ignite.Core.Impl.Binary.Marshaller.AddType(Type type, Int32 typeId, String typeName, Boolean userType, Boolean keepDeserialized, IBinaryNameMapper nameMapper, IBinaryIdMapper idMapper, IBinarySerializerInternal serializer, String affKeyFieldName, Boolean isEnum) 
    at Apache.Ignite.Core.Impl.Binary.Marshaller.AddUserType(BinaryTypeConfiguration typeCfg, TypeResolver typeResolver) 
    at Apache.Ignite.Core.Impl.Binary.Marshaller.GetDescriptor(Boolean userType, Int32 typeId, Boolean requiresType, String typeName, Type knownType) 
    at Apache.Ignite.Core.Impl.Binary.Marshaller.GetDescriptor(String typeName) 
    at Apache.Ignite.Core.Impl.Binary.Binary.GetBuilder(String typeName) 
    at MyCompany.DataFabric.Core.CacheManagers.Table.RowCacheManager.BuildRow(Int64 rowNumber, String row, Boolean setColumnFields) in C:\Users\me\Documents\GitLab\Platform\Core\CacheManagers\Table\RowCacheManager.cs:line 140 
    at MyCompany.DataFabric.Core.CacheManagers.Table.RowCacheManager.<>c__DisplayClass26_1.<WriteAsync>b__1(KeyValuePair`2 r) in C:\Users\me\Documents\GitLab\Platform\Core\CacheManagers\Table\RowCacheManager.cs:line 128 
    at System.Threading.Tasks.Parallel.<>c__DisplayClass42_0`2.<PartitionerForEachWorker>b__1() 
    at System.Threading.Tasks.Task.InnerInvokeWithArg(Task childTask) 
    at System.Threading.Tasks.Task.<>c__DisplayClass176_0.<ExecuteSelfReplicating>b__0(Object) 

這是我的代碼如下所示:

public async Task WriteAsync(IEnumerable<string> rows, long startRowNum = 0) { 
    // Create the cache if it doesn't exist, yet 
    await this.GetOrCreateRowCache(); 

    using (var ds = m_ignite.GetDataStreamer<string, object>(CacheName).WithKeepBinary<string, IBinaryObject>()) { 
     try { 
      ds.AllowOverwrite = true; 
      ds.Receiver = new RowStreamReceiver { 
       TableId = TableId 
      }; 

      Parallel.ForEach(rows.Select((r, i) => new KeyValuePair<long, string>(i, r)), r => { 
       var rowNum = r.Key + startRowNum; 
       if (rowNum % 10000 == 0) { 
        Console.WriteLine($"Put [Row: {r.Key}, Thread: {Thread.CurrentThread.ManagedThreadId}]"); 
       } 
       var pair = BuildRow(rowNum, r.Value, false); 
       // ReSharper disable once AccessToDisposedClosure 
       ds.AddData(pair); 
      }); 
     } finally { 
      Console.WriteLine("Flushing"); 
      ds.Flush(); 
     } 
    } 
} 

public KeyValuePair<string, IBinaryObject> BuildRow(long rowNumber, string row, bool setColumnFields = true) { 
    var builder = m_ignite.GetBinary().GetBuilder(TypeName); 

    var rowId = row.GetHashString(); 
    builder.SetField(PrimaryKeyName, rowId); 
    builder.SetField(RowNumberName, rowNumber); 
    builder.SetField(RawName, row); 

    if (setColumnFields) { 
     SetColumnFields(m_table, row, builder); 
    } 

    return new KeyValuePair<string, IBinaryObject>(rowId, builder.Build()); 
} 

回答

1

我複製和歸檔的bug:https://issues.apache.org/jira/browse/IGNITE-5931

這是一場種族競爭離子,我認爲它也存在於2.0中(這段代碼在2.1和2.0中是相同的)。還有另外兩個類似的檢查是正確完成的,期待一個多線程場景,但是這個被遺忘了。

解決方法1:在BinaryConfiguration註冊類型:

 var cfg = new IgniteConfiguration 
     { 
      BinaryConfiguration = new BinaryConfiguration 
      { 
       Types = new[] {"Row"} 
      } 
     }; 

解決方法2:同步訪問GetBuilder方法(把它放在一個鎖)。實際處理不一定處於鎖定狀態,因此性能不會受到影響。