Pull to refresh

Comments 9

100гб на 100 ярдов, это 1 кб на запись в среднем верно?? собственно откуда теоретически выйгрыш если в любой обычной субд, аля постгрес, обновить одну строку в 1кб размером занимает ровно столько же времени сколько и 1 колонку в этой в этой строке.

Не все строки обновляются одинаково часто, если взвесить по частоте обновления то с наивным алгоритмом одна запись была бы 10кб в среднем. Ну и экономим мы не астрономическое время (операции делаем батчевые, пытаться уменьшать летенси одной операции у нас не возникало необходимости), а cpu time, запись на диски, чтения с дисков, место на дисках, сеть. А эти штуки заметно уменьшаются.

Почему по старинке не делаете - набором таблиц, а документом сохраняете информацию? Таблица banners отдельно, отдельно embeddings, counters и так далее? И апдейтите свои счетчики - поля int в строках.

А то выглядит так - перешли на волне моды на NoSQL, а теперь героически боретесь с основополагающими недостатками документ-ориентированной технологии.

Даже сейчас считаю возможным выделить часто изменяющиеся данные типа счетчиков в отдельные таблицы, да и вообще говоря, применить не sql-сервера, а например, хранилища ключ-значение.

У нас довольно много сервисов потоковой обработки, и у них разные профили взаимодействия со стейтом. Ну и еще NDA есть, и конкретики не расскажешь. Поэтому далее несколько разрозненные аргументы, почему у нас так как есть.
Почему одна таблица?
* Среди всех стейтов может быть длинный хвост стейтов маленького размера и из-за этого суммарный размер ключей начинает нас волновать. Если делать несколько таблиц, то придется многократно хранить ключи и платить за это. (Это я не высасываю из пальца, несколько лет назад реально размышляли на такую тему)
* В одном сервисе нам критически важны быстрые лукапы по ключам, одна таблица тут помогает.
* В плоскую структуру наши стейты не разложить - получится неадекватное число колонок, а при разделении на небольшое число таблиц / колонок от работы с документами уйти не получится.

При этом у нас не везде одна таблица. У нас есть раздельные таблицы с одним множеством ключей там, где это необходимо/выгодно.

Про выбор БД, тут есть особенности разработки больших сервисов внутри больших IT компаний, брали YTsaurus, так как в нем был нужный функционал для обеспечения exactly once, его использовали ранее в отделе, и с командой YTsaurus можно взаимодействовать и заказывать фичи и улучшения :)

Обработчики обновляли один и тот же баннер, но у этого баннера один и тот же номер шарда, а значит, оба обработчика не могли пройти мимо обновления одного и того же значения оффсета в таблице. Но оффсеты мы обновляем исключительно транзакционно, при этом коммитим только после проверки открывшейся транзакции на ожидаемое значение. Этот механизм гарантирует, что хотя бы у одного обработчика либо упадёт проверка того, что оффсет ожидаемый, либо упадёт коммит транзакции с ошибкой конфликта записи. А когда у обработчика происходит ошибка, он полностью перезапускается, при этом сбрасывает весь свой кэш стейтов.

Кто нибудь понял о чем это, или все по диагонали читали?

На сколько я понял, номер шарда у них, это аналог версии баннера, а дальше делается просто CAS или Test And Set, как у многих атомарных операций - параллельно два обработчика меняют данные одно и того же баннера, но закоммитить изменения сможет только один из них, т.к. коммит выполнится только при условии, что версия баннера в базе совпадает с ожидаемой. Второй же обработчик увидит новый номер версии, проставленный первым, транзакция не пройдет и ему придется заново читать изменения из базы и снова пытаться повторить свои изменения.

это называется "оптимистический режим блокировок".

„На данный момент на маленькое событие обновления одного счётчика мы перезаписали всю колонку счётчиков, которая может иметь размер порядка десяти килобайт. Хотелось бы отправлять в БД только само произведённое изменение.

На помощь приходят бинарные дельта-кодеки, в частности, xdelta. Он позволяет вычислить diff между любой парой бинарных строк, а затем наложить его на оригинальную строку и получить новое значение. Это как git diff и git apply, только не с текстовыми файлами в репозитории, а с любыми бинарными строками.“

Если я правильно понял то логика следующая:

  • RDBMS это не модно и не молодёжно, поэтому все сделаем на key/value storage.

  • нам надо сэкономить данные на чтение/запись - давайте часть записи хранить в отдельном поле

  • А как будем обновлять? Посчитаем xdelta…

    было: пишем объект по ключу

    Стало: читаем по ключу/ вычисляем дельту, пишем дельту.

    Вместо одной операции на запись как писали выше в нормальную колонку БД где одно целое число надо заменить на другое и не надо ничего считать- нагородили огород с чтением/записью расчетом дельты.

    При этом предполагаем что пока мы читаем/считаем дельту никто это поле не обновит. И если надо поменять счётчик a и счётчик b одновременно, то просто создаём себе проблему на ровном месте, которую успешно преодолеваем…

у них там YTsaurus новый, это типа реляционная субд.

Sign up to leave a comment.