问题描述
从Apache Ignite 2.0升级到2.1(.Net)后,出现错误类型ID冲突[type1 ='Row',type2 ='Row',typeId = 113114]".升级后我没有更改任何代码,所以想知道关于如何创建和使用动态二进制对象的期望是否发生了变化?我看着AddType方法.也许它应该返回而不是抛出,并且该方法的名称可能会引起误解,并且应该为GetOrAddType?
I'm getting the error "Conflicting type IDs [type1='Row', type2='Row', typeId=113114]" after upgrading from Apache Ignite 2.0 to 2.1 (.Net). I didn't change any code after upgrading, so am wondering if the expectation on how to create and use dynamic Binary Objects changed? I looked at the AddType method. Maybe it should be returning instead of throwing, and maybe the name of the method is misleading and it should be GetOrAddType?
AddType Method: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());
}
推荐答案
我已复制并提交了该错误: https://issues.apache.org/jira/browse/IGNITE-5931
I've reproduced and filed the bug: https://issues.apache.org/jira/browse/IGNITE-5931
这是一个竞争条件,我认为它也存在于2.0中(这段代码在2.1和2.0中是相同的).在其他两个地方也可以正确地执行类似检查,但预期会出现多线程情况,但这一地方被遗忘了.
It's a race condition, and I think it exists in 2.0 as well (this piece of code is the same in 2.1 and 2.0). There are two other places where similar check is done correctly, expecting a multithreaded scenario, but this one was forgotten.
解决方法1 :在 BinaryConfiguration
中注册类型:
var cfg = new IgniteConfiguration
{
BinaryConfiguration = new BinaryConfiguration
{
Types = new[] {"Row"}
}
};
解决方法2 :同步对 GetBuilder
方法的访问(将其置于锁定状态).实际的处理不必处于锁定状态,因此性能不会受到影响.
Workaround 2: synchronize access to GetBuilder
method (put it in a lock). Actual processing does not have to be in a lock, so the performance won't be affected.
这篇关于Apache Ignite 2.1:获取“冲突类型ID"从2.0升级后出现错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!