2016-07-12 4 views
0

Я использую pyspark и pyspark-cassandra.Странное поведение при обновлении строки Cassandra

Я заметил это поведение на нескольких версиях Кассандры (3.0.x и 3.6.x) с помощью COPY, sstableloader, и теперь saveToCassandra в pyspark.

У меня есть следующая схема

CREATE TABLE test (
    id int, 
    time timestamp, 
    a int, 
    b int, 
    c int, 
    PRIMARY KEY ((id), time) 
) WITH CLUSTERING ORDER BY (time DESC); 

и следующие данные

(1, datetime.datetime(2015, 3, 1, 0, 18, 18, tzinfo=<UTC>), 1, 0, 0) 
(1, datetime.datetime(2015, 3, 1, 0, 19, 12, tzinfo=<UTC>), 0, 1, 0) 
(1, datetime.datetime(2015, 3, 1, 0, 22, 59, tzinfo=<UTC>), 1, 0, 0) 
(1, datetime.datetime(2015, 3, 1, 0, 23, 52, tzinfo=<UTC>), 0, 1, 0) 
(1, datetime.datetime(2015, 3, 1, 0, 32, 2, tzinfo=<UTC>), 1, 1, 0) 
(1, datetime.datetime(2015, 3, 1, 0, 32, 8, tzinfo=<UTC>), 0, 2, 0) 
(1, datetime.datetime(2015, 3, 1, 0, 43, 30, tzinfo=<UTC>), 1, 1, 0) 
(1, datetime.datetime(2015, 3, 1, 0, 44, 12, tzinfo=<UTC>), 0, 2, 0) 
(1, datetime.datetime(2015, 3, 1, 0, 48, 49, tzinfo=<UTC>), 1, 1, 0) 
(1, datetime.datetime(2015, 3, 1, 0, 49, 7, tzinfo=<UTC>), 0, 2, 0) 
(1, datetime.datetime(2015, 3, 1, 0, 50, 5, tzinfo=<UTC>), 1, 1, 0) 
(1, datetime.datetime(2015, 3, 1, 0, 50, 53, tzinfo=<UTC>), 0, 2, 0) 
(1, datetime.datetime(2015, 3, 1, 0, 51, 53, tzinfo=<UTC>), 1, 1, 0) 
(1, datetime.datetime(2015, 3, 1, 0, 51, 59, tzinfo=<UTC>), 0, 2, 0) 
(1, datetime.datetime(2015, 3, 1, 0, 54, 35, tzinfo=<UTC>), 1, 1, 0) 
(1, datetime.datetime(2015, 3, 1, 0, 55, 28, tzinfo=<UTC>), 0, 2, 0) 
(1, datetime.datetime(2015, 3, 1, 0, 55, 55, tzinfo=<UTC>), 1, 2, 0) 
(1, datetime.datetime(2015, 3, 1, 0, 56, 24, tzinfo=<UTC>), 0, 3, 0) 
(1, datetime.datetime(2015, 3, 1, 1, 11, 14, tzinfo=<UTC>), 1, 2, 0) 
(1, datetime.datetime(2015, 3, 1, 1, 11, 17, tzinfo=<UTC>), 2, 1, 0) 
(1, datetime.datetime(2015, 3, 1, 1, 12, 8, tzinfo=<UTC>), 1, 2, 0) 
(1, datetime.datetime(2015, 3, 1, 1, 12, 10, tzinfo=<UTC>), 0, 3, 0) 
(1, datetime.datetime(2015, 3, 1, 1, 17, 43, tzinfo=<UTC>), 1, 2, 0) 
(1, datetime.datetime(2015, 3, 1, 1, 17, 49, tzinfo=<UTC>), 0, 3, 0) 
(1, datetime.datetime(2015, 3, 1, 1, 24, 12, tzinfo=<UTC>), 1, 2, 0) 
(1, datetime.datetime(2015, 3, 1, 1, 24, 18, tzinfo=<UTC>), 2, 1, 0) 
(1, datetime.datetime(2015, 3, 1, 1, 24, 18, tzinfo=<UTC>), 1, 2, 0) 
(1, datetime.datetime(2015, 3, 1, 1, 24, 24, tzinfo=<UTC>), 2, 1, 0) 

К концу данных, есть две строки, которые имеют ту же метку времени.

(1, datetime.datetime(2015, 3, 1, 1, 24, 18, tzinfo=<UTC>), 2, 1, 0) 
(1, datetime.datetime(2015, 3, 1, 1, 24, 18, tzinfo=<UTC>), 1, 2, 0) 

Это мое понимание того, что, когда я сохраняю к Кассандре, один из них будет «выиграть» - там будет только одна строка.

После записи Кассандры используя

rdd.saveToCassandra(keyspace, table, ['id', 'time', 'a', 'b', 'c']) 

Ни строки, кажется, выиграл. Скорее, строки, похоже, «слились».

1 | 2015-03-01 01:17:43+0000 |  1 |  2 |  0 
    1 | 2015-03-01 01:17:49+0000 |  0 |  3 |  0 
    1 | 2015-03-01 01:24:12+0000 |  1 |  2 |  0 
    1 | 2015-03-01 01:24:18+0000 |  2 |  2 |  0 
    1 | 2015-03-01 01:24:24+0000 |  2 |  1 |  0 

Вместо чем 2015-03-01 01:24:18+0000 содержащий (1, 2, 0) или (2, 1, 0), она содержит (2, 2, 0).

Что здесь происходит? Я не могу для жизни понять, что это поведение вызвано.

ответ

1

Это малоизвестный эффект, связанный с объединением данных. Batching пишет присваивает одну и ту же метку времени всем вкладкам в пакете. Затем, если две записи сделаны с точной той же меткой времени, тогда существует специальное правило слияния, так как не было «последней» записи. Коннектор Spark Cassandra по умолчанию использует внутрисегментные партии, так что это очень вероятно, если у вас есть такой тип сглаживания значений.

Поведение с двумя идентичными метками времени записи является слиянием, основанным на Большом значении.

Учитывая Таблица (ключ, а, б)

Batch 
Insert "foo", 2, 1 
Insert "foo", 1, 2 
End batch 

Пакетный дает обе мутации ту же метку времени. Кассандра не может выбрать «последний-написанный», так как они оба произошли в одно и то же время, вместо этого он просто выбирает большую ценность этих двух. Объединенный результат будет

"foo", 2, 2 
+0

Спасибо, я подозревал, что подобное происходит, но не могло найти никакой информации об этом. Как на практике люди справляются с этим? Просто убедитесь, что у вас есть миллисекунда точных исторических данных? – dacox

+0

Ну, есть несколько вещей, которые вы можете сделать в зависимости от вашей цели. В большинстве случаев пользователи просто пытаются гарантировать, что в одной и той же партии не будут дублироваться первичные ключи.Если вы хотите сохранить обе записи в C *, вам нужно будет различать их как (например, с миллисекундами или TimeUUID) Некоторые пользователи прикрепляют отдельные временные метки для принудительного упорядочения (то есть, если каждая вставка имеет порядок возрастания, то они будут применяться в этом порядке.) У вас действительно нет этой опции, так как ваши партии построены автоматически. Это также теряет дубликаты. – RussS