LOCAL_ONE и неожиданная репликация данных с Cassandra

К вашему сведению. Мы запускаем этот тест с Cassandra 2.1.12.1047 | DSE 4.8.4

У нас есть простая таблица в Cassandra, в которой содержится 5000 строк данных. Некоторое время назад в качестве меры предосторожности мы добавили мониторинг для каждого экземпляра Cassandra, чтобы гарантировать, что он имеет 5000 строк данных, потому что наш фактор репликации обеспечивает это, то есть у нас есть 2 реплики в каждом регионе, и у нас есть 6 серверов в нашем кластере разработки.

CREATE KEYSPACE example WITH replication = {'class': 'NetworkTopologyStrategy', 'ap-southeast-1-A': '2', 'eu-west-1-A': '2', 'us-east-1-A': '2'} AND durable_writes = true;

Недавно мы принудительно остановили сервер, чтобы имитировать сбой, и подключили новый, чтобы посмотреть, что произойдет. Мы также удалили старый узел, используя nodetool removenode, чтобы в каждом регионе мы ожидали, что все данные будут существовать на каждом сервере.

Как только новый сервер подключился к сети, он присоединился к кластеру и, похоже, начал репликацию данных. Мы предполагаем, что, поскольку он находится в режиме начальной загрузки, он будет нести ответственность за получение необходимых данных из кластера. ЦП окончательно упал примерно через час, и мы предположили, что репликация завершена.

Однако наши мониторы, которые намеренно выполняют запросы с использованием LOCAL_ONE на каждом сервере, сообщили, что на всех серверах было 5000 строк, а новый сервер, который был переведен в оперативный режим, застрял примерно на 2600 строках. Мы предположили, что, возможно, он все еще воспроизводится, поэтому мы оставили его на некоторое время, но оно осталось на том же уровне.

Итак, мы запустили nodetool status для проверки и получили следующее:

$ nodetool status my_keyspace
Datacenter: ap-southeast-1-A
======================================
Status=Up/Down
|/ State=Normal/Leaving/Joining/Moving
--  Address         Load       Tokens  Owns (effective)  Host ID                               Rack
UN  54.255.17.28    7.9 GB     256     100.0%            a0c45f3f-8479-4046-b3c0-b2dd19f07b87  ap-southeast-1a
UN  54.255.64.1     8.2 GB     256     100.0%            b91c5863-e1e1-4cb6-b9c1-0f24a33b4baf  ap-southeast-1b
Datacenter: eu-west-1-A
=================================
Status=Up/Down
|/ State=Normal/Leaving/Joining/Moving
--  Address         Load       Tokens  Owns (effective)  Host ID                               Rack
UN  176.34.207.151  8.51 GB    256     100.0%            30ff8d00-1ab6-4538-9c67-a49e9ad34672  eu-west-1b
UN  54.195.174.72   8.4 GB     256     100.0%            f00dfb85-6099-40fa-9eaa-cf1dce2f0cd7  eu-west-1c
Datacenter: us-east-1-A
=================================
Status=Up/Down
|/ State=Normal/Leaving/Joining/Moving
--  Address         Load       Tokens  Owns (effective)  Host ID                               Rack
UN  54.225.11.249   8.17 GB    256     100.0%            0e0adf3d-4666-4aa4-ada7-4716e7c49ace  us-east-1e
UN  54.224.182.94   3.66 GB    256     100.0%            1f9c6bef-e479-49e8-a1ea-b1d0d68257c7  us-east-1d 

Итак, если сервер сообщает, что ему принадлежит 100% данных, почему запрос LOCAL_ONE дает нам только примерно половину данных?

Когда я выполнил LOCAL_QUORUM запрос, он вернул 5000 строк, а с этого момента вперед вернул 5000 даже для LOCAL_ONE запросов.

Хотя LOCAL_QUORUM решила проблему в этом случае, нам, возможно, в будущем потребуется выполнять другие типы запросов, исходя из предположения, что каждый сервер а) имеет данные, которые он должен иметь, б) знает, как удовлетворить запросы, когда у него нет данных, т. Е. он знает, что данные находятся где-то еще в кольце.

ДАЛЬНЕЙШЕЕ ОБНОВЛЕНИЕ через 24 часа - ПРОБЛЕМА НАМНОГО ХУЖЕ

Поэтому в отсутствие каких-либо отзывов по этой проблеме я продолжил экспериментировать с этим в кластере, добавив дополнительные узлы. Согласно https://docs.datastax.com/en/cassandra/1.2/cassandra/operations/ops_add_node_to_cluster_t.html, я выполнил все шаги, рекомендованные для добавления узлов в кластер и, по сути, увеличения емкости. Я считаю, что предпосылка Cassandra заключается в том, что при добавлении узлов кластер несет ответственность за перебалансировку данных и в течение этого времени получать данные из позиции в кольце, в которой он находится, если это не то место, где оно должно быть.

К сожалению, это совсем не так. Вот мое новое кольцо:

Datacenter: ap-southeast-1-A
======================================
Status=Up/Down
|/ State=Normal/Leaving/Joining/Moving
--  Address         Load       Tokens  Owns (effective)  Host ID                               Rack
UN  54.255.xxx.xxx  8.06 GB    256     50.8%             a0c45f3f-8479-4046-b3c0-b2dd19f07b87  ap-southeast-1a
UN  54.254.xxx.xxx  2.04 MB    256     49.2%             e2e2fa97-80a0-4768-a2aa-2b63e2ab1577  ap-southeast-1a
UN  54.169.xxx.xxx  1.88 MB    256     47.4%             bcfc2ff0-67ab-4e6e-9b18-77b87f6b3df3  ap-southeast-1b
UN  54.255.xxx.xxx  8.29 GB    256     52.6%             b91c5863-e1e1-4cb6-b9c1-0f24a33b4baf  ap-southeast-1b
Datacenter: eu-west-1-A
=================================
Status=Up/Down
|/ State=Normal/Leaving/Joining/Moving
--  Address         Load       Tokens  Owns (effective)  Host ID                               Rack
UN  54.78.xxx.xxx   8.3 GB     256     49.9%             30ff8d00-1ab6-4538-9c67-a49e9ad34672  eu-west-1b
UN  54.195.xxx.xxx  8.54 GB    256     50.7%             f00dfb85-6099-40fa-9eaa-cf1dce2f0cd7  eu-west-1c
UN  54.194.xxx.xxx  5.3 MB     256     49.3%             3789e2cc-032d-4b26-bff9-b2ee71ee41a0  eu-west-1c
UN  54.229.xxx.xxx  5.2 MB     256     50.1%             34811c15-de8f-4b12-98e7-0b4721e7ddfa  eu-west-1b
Datacenter: us-east-1-A
=================================
Status=Up/Down
|/ State=Normal/Leaving/Joining/Moving
--  Address         Load       Tokens  Owns (effective)  Host ID                               Rack
UN  54.152.xxx.xxx  5.27 MB    256     47.4%             a562226a-c9f2-474f-9b86-46c3d2d3b212  us-east-1d
UN  54.225.xxx.xxx  8.32 GB    256     50.3%             0e0adf3d-4666-4aa4-ada7-4716e7c49ace  us-east-1e
UN  52.91.xxx.xxx   5.28 MB    256     49.7%             524320ba-b8be-494a-a9ce-c44c90555c51  us-east-1e
UN  54.224.xxx.xxx  3.85 GB    256     52.6%             1f9c6bef-e479-49e8-a1ea-b1d0d68257c7  us-east-1d

Как вы увидите, я увеличил размер кольца вдвое, и фактическое владение составляет примерно 50% на сервер, как и ожидалось (мой коэффициент репликации составляет 2 копии в каждом регионе). Однако, на самом деле, вы можете видеть, что некоторые серверы абсолютно не загружены (они новые), в то время как другие имеют чрезмерную нагрузку на них (они старые и явно не происходит распределения данных).

Само по себе это не вызывает беспокойства, поскольку я верю в возможности Кассандры и ее способность в конечном итоге получать данные в нужном месте. Меня очень беспокоит то, что моя таблица с ровно 5000 строками теперь больше не имеет 5000 строк ни в одном из трех регионов.

# From ap-southeast-1

cqlsh> CONSISTENCY ONE;
Consistency level set to ONE.

cqlsh> select count(*) from health_check_data_consistency;

 count
-------
  3891

cqlsh> CONSISTENCY LOCAL_QUORUM;
Consistency level set to LOCAL_QUORUM.

cqlsh> select count(*) from health_check_data_consistency;

 count
-------
  4633


# From eu-west-1

cqlsh> CONSISTENCY ONE;
Consistency level set to ONE.

cqlsh> select count(*) from health_check_data_consistency;

 count
-------
  1975

cqlsh> CONSISTENCY LOCAL_QUORUM;
Consistency level set to LOCAL_QUORUM.

cqlsh> select count(*) from health_check_data_consistency;

 count
-------
  4209


# From us-east-1

cqlsh> CONSISTENCY ONE;
Consistency level set to ONE.

cqlsh> select count(*) from health_check_data_consistency;

 count
-------
  4435

cqlsh> CONSISTENCY LOCAL_QUORUM;
Consistency level set to LOCAL_QUORUM.

cqlsh> select count(*) from health_check_data_consistency;

 count
-------
  4870

Так серьезно, что здесь происходит? Подведем итоги:

  • у меня коэффициент репликации 'ap-southeast-1-A': '2', 'eu-west-1-A': '2', 'us-east-1-A': '2', поэтому каждый регион должен иметь возможность полностью удовлетворить запрос.
  • Создание новых экземпляров не должно вызывать у меня потери данных, но, по-видимому, мы делаем это даже с LOCAL_QUORUM
  • Каждый регион имеет свой взгляд на данные, но я не ввел никаких новых данных, только новые серверы, которые затем загружаются автоматически.

Тогда я подумал, почему бы не сделать QUORUM запрос по всему многорегиональному кластеру. К сожалению, это полностью не удается:

cqlsh> CONSISTENCY QUORUM;
Consistency level set to QUORUM.

cqlsh> select count(*) from health_check_data_consistency;
OperationTimedOut: errors={}, last_host=172.17.0.2

Затем мне исполнилось 14 лет, и это тоже не удалось. Все, что я вижу в журналах, это следующее:

INFO  [SlabPoolCleaner] 2016-03-03 19:16:16,616  ColumnFamilyStore.java:1197 - Flushing largest CFS(Keyspace='system_traces', ColumnFamily='events') to free up room. Used total: 0.33/0.00, live: 0.33/0.00, flushing: 0.00/0.00, this: 0.02/0.02
INFO  [SlabPoolCleaner] 2016-03-03 19:16:16,617  ColumnFamilyStore.java:905 - Enqueuing flush of events: 5624218 (2%) on-heap, 0 (0%) off-heap
INFO  [MemtableFlushWriter:1126] 2016-03-03 19:16:16,617  Memtable.java:347 - Writing Memtable-events@732346653(1.102MiB serialized bytes, 25630 ops, 2%/0% of on/off-heap limit)
INFO  [MemtableFlushWriter:1126] 2016-03-03 19:16:16,821  Memtable.java:382 - Completed flushing /var/lib/cassandra/data/system_traces/events/system_traces-events-tmp-ka-3-Data.db (298.327KiB) for commitlog position ReplayPosition(segmentId=1456854950580, position=28100666
)
INFO  [ScheduledTasks:1] 2016-03-03 19:16:21,210  MessagingService.java:929 - _TRACE messages were dropped in last 5000 ms: 212 for internal timeout and 0 for cross node timeout

Это происходит на каждом сервере, на котором я выполняю запрос.

Проверяю кластер, вроде все синхронизировано

$ nodetool describecluster;
Cluster Information:
    Name: Ably
    Snitch: org.apache.cassandra.locator.DynamicEndpointSnitch
    Partitioner: org.apache.cassandra.dht.Murmur3Partitioner
    Schema versions:
            51e57d47-8870-31ca-a2cd-3d854e449687: [54.78.xxx.xxx, 54.152.xxx.xxx, 54.254.xxx.xxx, 54.255.xxx.xxx, 54.195.xxx.xxx, 54.194.xxx.xxx, 54.225.xxx.xxx, 52.91.xxx.xxx, 54.229.xxx.xxx, 54.169.xxx.xxx, 54.224.xxx.xxx, 54.255.xxx.xxx]

ДАЛЬНЕЙШЕЕ ОБНОВЛЕНИЕ через час

Кто-то предположил, что, возможно, это просто связано с тем, что запросы диапазона не работают должным образом. Таким образом, я написал простой скрипт, который запрашивал каждую из 5 тыс. Строк отдельно (у них есть диапазон идентификаторов 1-> 5,000). К сожалению, результаты такие, как я и опасался, у меня отсутствуют данные. Я пробовал это с LOCAL_ONE, LOCAL_QUORUM и событием QUORUM.

ruby> (1..5000).each { |id| put "#{id} missing" if session.execute("select id from health_check_data_consistency where id = #{id}", consistency: :local_quorum).length == 0 }
19 missing, 61 missing, 84 missing, 153 missing, 157 missing, 178 missing, 248 missing, 258 missing, 323 missing, 354 missing, 385 missing, 516 missing, 538 missing, 676 missing, 708 missing, 727 missing, 731 missing, 761 missing, 863 missing, 956 missing, 1006 missing, 1102 missing, 1121 missing, 1161 missing, 1369 missing, 1407 missing, 1412 missing, 1500 missing, 1529 missing, 1597 missing, 1861 missing, 1907 missing, 2005 missing, 2168 missing, 2207 missing, 2210 missing, 2275 missing, 2281 missing, 2379 missing, 2410 missing, 2469 missing, 2672 missing, 2726 missing, 2757 missing, 2815 missing, 2877 missing, 2967 missing, 3049 missing, 3070 missing, 3123 missing, 3161 missing, 3235 missing, 3343 missing, 3529 missing, 3533 missing, 3830 missing, 4016 missing, 4030 missing, 4084 missing, 4118 missing, 4217 missing, 4225 missing, 4260 missing, 4292 missing, 4313 missing, 4337 missing, 4399 missing, 4596 missing, 4632 missing, 4709 missing, 4786 missing, 4886 missing, 4934 missing, 4938 missing, 4942 missing, 5000 missing

Как видно из вышеизложенного, это означает, что примерно 1,5% моих данных больше не доступны.

Так что я в тупике. Мне действительно нужен совет, потому что у меня определенно сложилось впечатление, что Cassandra была специально разработана для горизонтального масштабирования по запросу. Любая помощь очень ценится.


person Matthew O'Riordan    schedule 02.03.2016    source источник


Ответы (2)


По поводу собственности. Это основано на владении токеном, а не на фактических данных. Таким образом, заявленное владение в каждом случае выглядит правильным независимо от объема данных на каждом узле.

Во-вторых, вы не можете гарантировать согласованность с двумя узлами (если вы не жертвуете доступностью и не используете CL = ALL). КВОРУМ = большинство. Вам нужно как минимум три узла на каждый DC, чтобы действительно получить кворум. Если для вас важна согласованность, разверните три узла на каждый контроллер домена и выполните QUORUM операций чтения и записи.

Время ожидания SELECT count (*) на контроллерах домена истекает. Между вашими центрами обработки данных us и ap, вероятно, существует задержка в несколько сотен мс. Плюс счетчик выбора (*) - дорогостоящая операция.

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

При этом, похоже, у вас действительно есть проблема с начальной загрузкой, потому что новые узлы не получают все данные. Сначала я исправил все узлы и после этого убедился, что все они имеют 5000 записей. Это даст вам знать, что потоковая передача не прерывается. Затем повторите замену узла, как и раньше. На этот раз контролируйте с помощью netstats nodetool и смотрите логи. Публикуйте что-нибудь странное. И не забывайте, что вам нужно запустить очистку nodetool, чтобы удалить данные со старых узлов.

Можете ли вы описать конфигурацию вашего оборудования (ОЗУ, ЦП, диск и т. Д.)?

person Iain    schedule 03.03.2016
comment
Спасибо за ответ Иэн. You can’t guarantee consistency with two nodes - Но кворум в C * docs определяется как (sum_of_replication_factors / 2) + 1. Итак, если в одном DC у нас есть 2 узла с RF 2, то это 2/2 + 1, что равно 2. Почему мы не можем гарантировать согласованность? When you do a QUORUM read C* is going to fix inconsistent data with a read repair - Не так, к сожалению, сейчас не хватает 56 из 5000 строк. Запрос одной строки с CL ALL завершается ошибкой. Ремонт запущенного узла сейчас, довольно утомительный для серверов и очень медленный (пока 4 часа на пространство ключей, 8 пространств ключей), будет обновлен после завершения. - person Matthew O'Riordan; 04.03.2016
comment
Иан, что касается твоего комментария Regarding ownership. This is based on token ownership, not actual data. So the reported ownership in each case looks correct regardless of data volume on each node.. С тех пор я выполнил полный ремонт кластера, и теперь, когда он завершен, я все еще вижу ОГРОМНЫЙ дисбаланс нагрузки, то есть 8 ГБ на старом сервере и 500 МБ на новом сервере. Каким же образом Cassandra в конечном итоге гарантирует, что данные действительно правильно сегментированы в соответствии с владельцем токена? Без правильного сегментирования данных существует серьезный риск потери данных. - person Matthew O'Riordan; 06.03.2016

Я должен был сказать, что вы не можете гарантировать согласованность И доступность. Поскольку ваш запрос кворума по сути является ВСЕМ запросом. Единственный способ запросить, когда один из узлов не работает, - это снизить CL. И это не приведет к восстановлению чтения, если данные на доступном узле несовместимы.

После выполнения ремонта вам также необходимо выполнить очистку на старых узлах, чтобы удалить данные, которыми они больше не владеют. Кроме того, восстановление не удалит удаленные данные / данные TTLd до истечения периода gc_grace_seconds. Так что, если у вас есть что-то из этого, он останется как минимум на gc_grace_seconds.

Вы что-нибудь нашли в журналах? Вы можете поделиться своей конфигурацией?

person Iain    schedule 15.03.2016