Ответ 1
Короткий ответ: У них есть условие гонки, которое, по их мнению, разрешено в 1.1.8...
Длинный ответ:
Я получаю эту ошибку все время на одном из моих кластеров. У меня есть тестовые машины с действительно медленными жесткими дисками и создание одной или двух таблиц достаточно, чтобы получить ошибку, когда у меня есть 4 узла на двух отдельных компьютерах.
Ниже у меня есть копия трассировки стека из моей установки Cassandra 3.7. Хотя ваша версия была 2.1.3, я был бы удивлен, что эта часть кода сильно изменилась.
Как мы видим, исключение происходит в функции validateCompatibility()
. Это требует, чтобы новые и старые версии MetaData были равны:
- ksName (имя ключа)
- cfName (имя столбца)
- cfId (columnfamily UUID)
- flags (isSuper, isCounter, isDense, isCompound)
- компаратор (ключ сортировка компаратор)
Если какое-либо из этих значений не совпадает между старыми и новыми метаданными, тогда процесс вызывает исключение. В нашем случае значения cfId
различны.
Подняв стек, у нас есть apply()
, который вызывает validateCompatibility()
сразу.
Далее мы имеем updateTable()
. Точно так же он вызывает apply()
почти сразу. Сначала он вызывает getCFMetaData()
для извлечения текущих данных семейства столбцов ( "старый" ), которые будут сопоставлены с новыми данными.
Далее мы видим updateKeyspace()
. Эта функция вычисляет a diff
, чтобы узнать, что изменилось. Затем он сохраняет это в каждом типе данных. Таблица 2-го после Тип...
До этого у них есть mergeSchema()
, который вычисляет то, что изменилось на уровне Keyspace. Затем он удаляет пространства ключей, которые были удалены, и генерирует новые временные пространства для тех, которые были обновлены (и для новых областей ключей). Наконец, они перебирают новые области ключей, вызывающие updateKeyspace()
для каждого из них.
Далее в стеке мы видим интересную функцию: mergeSchemaAndAnnounceVersion()
. Этот будет обновлять версию после того, как области ключей были обновлены в памяти и на диске. Версия схемы включает в себя cfId
, которая несовместима и, таким образом, генерирует исключение. Часть Announce
должна отправить сообщение сплетни другим узлам о том, что этот node теперь знает о новой версии определенной схемы.
Далее мы видим нечто, называемое MigrationTask
. Это сообщение, используемое для переноса изменений между узлами Cassandra. Полезная нагрузка сообщения представляет собой набор мутаций (которые обрабатываются функцией mergeSchema()
.)
Остальная часть стека показывает только функции run()
, которые представляют собой различные типы функций, используемых для обработки сообщений.
В моем случае для меня проблема решена немного позже, и все хорошо. Мне нечего делать, чтобы схема окончательно синхронизировалась. как и ожидалось. Однако это мешает мне создавать все мои таблицы за один раз. Таким образом, я считаю, что сообщения о миграции не поступают в ожидаемом порядке. Должен быть тайм-аут, который обрабатывается путем повторного отправки события и генерирует его.
Итак, давайте посмотрим на код, отправляющий сообщение, в первую очередь, вы видите его в MigrationManager. Здесь у нас есть параметр MIGRATION_DELAY_IN_MS
, связанный со старой проблемой, Schema push/pull race, которая заключалась в том, чтобы избежать состояния гонки. Ну... вот ты. Поэтому они знают, что есть возможное состояние гонки и пытаться избежать этого, они добавили немного задержки там. Одна часть этого исправления включает проверку версии. Если версии уже равны, вообще избегайте обновления (т.е. Игнорируйте эту сплетню).
if (Schema.instance.getVersion().equals(currentVersion))
{
logger.debug("not submitting migration task for {} because our versions match", endpoint);
return;
}
Задержка, о которой мы говорим, составляет одну минуту:
public static final int MIGRATION_DELAY_IN_MS = 60000;
Можно подумать, что хватит одной минуты, но почему-то я все равно получаю ошибку все время.
Дело в том, что их код не ожидает, что несколько изменений происходят один за другим, включая большие задержки, как у меня. Поэтому, если бы я должен был создать один стол, а затем делать другие вещи, я был бы в порядке. С другой стороны, когда я хочу создать 20 таблиц подряд на этих медленных машинах, сообщение о сплетнях из предыдущего изменения схемы прибывает поздно (т.е. После того, как новая команда CREATE TABLE пришла к этому node.) Это, когда я получу эта ошибка. Самая худшая часть, я думаю, заключается в том, что это ложная ошибка (то есть она говорит мне, что сплетни были позже, а не то, что моя схема недействительна, а схема сообщения сплетни является старой).
org.apache.cassandra.exceptions.ConfigurationException: Column family ID mismatch (found 122a2d20-9e13-11e6-b830-55bace508971; expected 1213bef0-9e
at org.apache.cassandra.config.CFMetaData.validateCompatibility(CFMetaData.java:790) ~[apache-cassandra-3.9.jar:3.9]
at org.apache.cassandra.config.CFMetaData.apply(CFMetaData.java:750) ~[apache-cassandra-3.9.jar:3.9]
at org.apache.cassandra.config.Schema.updateTable(Schema.java:661) ~[apache-cassandra-3.9.jar:3.9]
at org.apache.cassandra.schema.SchemaKeyspace.updateKeyspace(SchemaKeyspace.java:1350) ~[apache-cassandra-3.9.jar:3.9]
at org.apache.cassandra.schema.SchemaKeyspace.mergeSchema(SchemaKeyspace.java:1306) ~[apache-cassandra-3.9.jar:3.9]
at org.apache.cassandra.schema.SchemaKeyspace.mergeSchemaAndAnnounceVersion(SchemaKeyspace.java:1256) ~[apache-cassandra-3.9.jar:3.9]
at org.apache.cassandra.service.MigrationTask$1.response(MigrationTask.java:92) ~[apache-cassandra-3.9.jar:3.9]
at org.apache.cassandra.net.ResponseVerbHandler.doVerb(ResponseVerbHandler.java:53) [apache-cassandra-3.9.jar:3.9]
at org.apache.cassandra.net.MessageDeliveryTask.run(MessageDeliveryTask.java:64) [apache-cassandra-3.9.jar:3.9]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_111]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_111]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_111]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_111]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_111]