Pull to refresh
0
0
Send message

Что-то у меня не сходится: карьера — это то, что выстраивается во время трудоспособной и активной фазы жизни, начиная лет эдак с 20 плюс-минус. При этом карьера строится на работе, с 40-часовой рабочей неделей, как правило. 40-часовая рабочая неделя на самом деле как минимум 45-часовая, поскольку включает в себя «перерыв на обед». Если человек не занимается депривацией сна, то получается, что из 112 часов активного бодрствования в неделю, 45 он проводит в рабочей обстановке. Да, не все 52 недели в году проходят в таком ритме, но у меня вопрос: какова должна быть продолжительность оплачиваемого отпуска, чтобы соотношение 45:112 (это примерно 2:5) начало напоминать 1:5?

Также для успешной карьеры необходимо накопить некоторые знания и навыки, а время для это «отщипывается» как раз из оставшихся трех пятых «свободного времени». Тут, конечно, можно вступить в дискуссию: мол мы советуем не тратить жизнь на то, что не нравится, поэтому это будет ощущаться как хобби. Первые 10-15 лет так может и будет, а дальше закончится молодость, окажется, что тело нельзя оставлять сидеть перед монитором по 10-12 часов в сутки — нужна физическая активность. И в этот момент могут начать появляться новые хобби, которые в силу новизны потеснят то, чему вы уже посвятили пару тысяч часов своего досуга.

Но самая мерзкая часть подобных «карьерных манипуляций» заключается в том, что некто, потративший, условно говоря, 200-300 часов на построение своего дела, а затем поддерживающий его ценою 1-2 часов в день для координирования труда наемных сотрудников, действительно говорит правду: у него-то work-life balance может быть даже куда лучше, чем пресловутые 1:5. Однако если кто-то из простых работяг, вкладывающий в его дело как минимум в два раза больше своего активного времени попросит дополнительный выходной/отпуск — мы же все понимаем, что владелец бизнеса расскажет о том, почему это невозможно и как ему, генеральному директору, приходится быть доступным 7 дней в неделю для игры в гольф с деловыми партнерами.

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

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

Здоровая простыня находится в одной единице трансляции, а куча маленьких файлов может быть разбросана по различным объектным файлам. С подобным может справиться ICC, но на больших проектах это приведет к взрывному росту времени компиляции.
использование уязвимости bashdoor (shellshock) для получения файла /etc/passwd

А что такого секретного в /etc/passwd?

Также могу посоветовать использовать curl -L — он самостоятельно пройдет по редиректам.
Более насущный вопрос: попадает ли Steam под этот закон?
>1. И зачастую многие кейсы написать на Lua проще чем на SQL
SELECT… FROM a LEFT JOIN b on a.field = b.field ORDER BY… OFFSET x LIMIT y на SQL записывается очень просто. «DELETE FROM t WHERE secondary_nonuniq_key < y» или «UPDATE a SET field=field1+field2 WHERE non_uniq_key > x AND non_key_filed < y»— еще проще. Вы точно видели, _как_ это реализуется в тарантуле на lua? Приятного мало, очень много способов прострелить себе ногу.
Не понимаю, почему в штатной поставке нет проверенных и оптимизированных разработчиками функций для выполнения таких задач.

>3. оверхед будет зависеть от размера туплов. Копия базы хранится в памяти не будет
Не совсем вас понял: от размера или от количества? Потому что если от размера tuples, то это выглядит как копирование (или там copy-on-write — скопируются только tuples, которые были изменены во время отправки запроса?). Меня сильно смущает, что iproto-пакет содержит длину — возникает ощущение, что данные предварительно сериализуются и копируются во временный буфер.

>4. можете показать пример кода, чтобы было чуточку понятней?
http://pastebin.com/b4Y5u3CW

>5. Попробуйте 1.6.8. Там очень много доработок в аллокаторе.
Честно говоря, нет желания заниматься бенчмарками, потому что перехода на 1.6 не будет без процедуры миграции данных.

>6. 7.
Хотелось бы увидеть ответы на эти вопросы — они не требуют ни бенчмарков, ни исследований (при условии, конечно, что в проекте есть разработчики, которые хорошо знают его внутренности — не сочтите за грубость).

>8. Но по нашему опыту и опыту многих наших кастомеров
Я, конечно, не кастомер (то есть, не платил деньги за саппорт), но вот вам «реальный кейс» (кстати, надеюсь, вы насладитесь краткостью конструкции join): http://pastebin.com/tYttKMdZ
И прежде чем вы будете рекомендовать денормализацию, хочу заметить, что space0 => space1 и space1 => space2 — это many-to-one, причем «many» — это действительно много, и изменения в space2 должны быть сразу видимы в выборках.
Кстати, было бы круто, если бы вы на данном конкретном примере поделились, как можно обойти space1 по HASH-индексу в условиях изменения данных. По TREE я и сам умею.

>9. Мы работаем сейчас над миграцией.
Знаете, если бы я был вашим клиентом с tarantool 1.5, для которого выходят только багфиксы в течение последнего года и вы порекомендовали мне перейти на 1.6, я был бы весьма недоволен таким ходом вещей.
Такое ощущение, что статью писали копирайтеры на аутсорсе, настолько чудовищно много технических деталей замалчивается.

>БД — это нечто надёжное, с транзакциями, серверным языком запросов.
А как с «серверным языком запросов у tarantool»? Все еще нужно писать join-ы руками? Что делать, когда есть необходимость выбрать значительную часть dataset-а по нетривиальному условию? Писать server-side lua программу плюс клиентское приложения под последовательный вызов этой серверной функции?

>Чтение файлов в память с магнитного диска происходит со скоростью 100 Мб/с. То есть, например, база данных в 100 Гб считается за 1000 с — примерно 15 мин.
Правда время простоя будет существенно больше, потому что данные надо не только прочитать с диска, но и перестроить индексы. Иногда — много индексов. Будьте готовы к «холодному старту» за полчаса минимум. И если что-то произойдет и с репликой — добро пожаловать в получасовой downtime.

И, раз уж вы говорите о больших объемах данных, можете ответить на пару вопросов:
1) Что произойдет, если я сделаю «select *» из огромной базы? От чего будет зависеть дополнительный оверхед по памяти? От размера tuple-ов или от их количества? В какой момент эта дополнительная память будет освобождена: после полного вычитывания запроса клиентом или «по мере отправки»?
2) Упаковка tuple-ов, выбранных из тарантула, в lua-шную таблицу делает дубликаты этих tuples?

>У нас используется свой собственный аллокатор, типа Slab-аллокатора, позволяющий минимизировать влияние фрагментации памяти.
Позвольте спросить, каким образом? Без переноса данных между slab-ами одного класса, при определенных паттернах нагрузки возникает забавная ситуация, когда heap состоит из огромного количества полупустых slab-ов «мелких» объектов, а на выделение более крупного объекта памяти уже не хватает. К сожалению, сталкивался лично в 1.5 при «разрастании» tuple-ов. «Лечил» рестартом.

>Если вам нужно хранить 1 млрд строк, в каждой из которых десять полей, размер поля — четыре байта, то это будет 4 х 10 х 1 млрд плюс 1–10% оверхеда на управляющие структуры.
Простите, но как же вторичные индексы? Мне вот, например, не хочется выяснять из кода, дублируются ли значения ключевых полей в индексы, или используется указатель на поле в tuple-е? Между прочим, очень животрепещущий вопрос, когда ключ занимает «значительную часть» tuple.

И коль скоро речь зашла об индексах, есть ли способ обойти space с HASH-индексом по primary key в условиях изменения space-а? В РСУБД даже в таком случае «select *» предсказуемо себя ведет.

Есть какие-то планы на использование многоядерности при обработке немодифицирующих запросов? При использовании «lua-join-ов» задекларированные «сотни тысяч запросов в секунду» очень быстро превращаются в «пару десятков тысяч», причем узким местом становится именно CPU, а не RAM, так что шардинг в таких условиях видится костылем, а не панацеей.

Я правильно понимаю, что версия 1.5 теперь abandoned и миграция данных 1.5 => 1.6+ — моя головная боль? Запрос «tarantool migration guide» выводит на репозиторий сотрудника Mail.Ru с, кхм, не совсем очевидной инструкцией. Есть ли какие-то гарантии (понимаю, в контексте бесплатного open source продукта это звучит неуместно, но все же), что эта история не повторится в ближайшее время, когда в текущем формате сериализации обнаружится «фатальный недостаток»? Почему просто нельзя сделать в 1.6 reader снапшотов и xlog в формате 1.5? Набор примитивный операций из 1.5 навряд ли был «урезан» в 1.6.
Какая-то чрезвычайно сомнительная уязвимость: возможность запихнуть путь длиной 2Gb уже само по себе может вызвать DoS, когда попытка выделить следующую пару гигабайт под пути закончится ENOMEM-ом.

Вообще странная пошла мода вешать «критические» ярлыки на всякую минорщину: нет proof of concept эксплоита хотя бы без ASLR => о каком RCE речь?

P. S. Кстати, в посте замалчивается важная деталь: теоретической возможности RCE нужно «всего лишь» каким-то чдом выставить executable-бит на страницах выделенной памяти, либо иметь W+X страницы с кодом. Даже при отключенном ASLR шансы выполнить что-то злоумышленнически-вразумительное навряд ли будут существенно больше нуля.
>Когда такие люди допускают такие ошибки…
Если бы был язык, в котором ошибки подобного рода были невозможны, все бы уже писали на нем.
Во-первых, все замечательно решается без шаблонов и предупреждений:
if (filelength & ~(unsigned long)(size_t)-1) {
/* error fillength is too large */
}


Во-вторых, считается хорошим тоном нужность подобных проверок определять в configure time (когда запускается cmake или иной аналог configure-скриптов), соответственно в итоге мы никогда не получим «condition always true» для совпадающих по размеру unsigned long и size_t.

В-третьих, если почитать стандарт, то можно написать намного понятнее и также без предупреждений (gcc-4.8.5):
#include <limits.h>

if (filelength > SIZE_MAX) {
/* file too large */
}
>Tarantool в пике делает 300К селектов на 1 ядре
Это при каких условиях?
На официальном сайте тарантула есть бенчмарк http://tarantool.org/benchmark.html, показывающий в районе 100k select-ов в секунду, а вы говорите о 300k.

>На один физический сервер — умножайте на 24
А память на 24 умножать не затратно будет?

>Шардить по ядрам
А потому ходить в шарды черед прокси (кстати, многопоточную или single-threaded?) и в итоге придем к тому, что «лучше бы вовсе не шардили».
Кстати, availability (не говоря уже о запросах «посчитать что-то среди имеющихся данных) страдает от шабрдинга, т. к. возрастает вероятность недоступности одного из шардов. Плюс увеличивается время старта при использовании AVLTREE-индексов.
Но задача мониторинга — привлечь внимание к проблемным ситуациям. Если p99 = 1000ms может быть проблемой, то лучше это честно нарисовать + дать возможность изменять масштаб времени. Тогда будет прекрасно видно, что за одним «проблемным пикселем» скрывалось несколько интервалов и более подробно проанализируем именно интервал с p99 = 1000ms.
>По нашему опыту и тестам Тарантул быстрее HandlerSocket, причем в разы быстрее
Вот здесь http://yoshinorimatsunobu.blogspot.ru/2010/10/using-mysql-as-nosql-story-for.html пишут о 750k select-ов по primary key в секунду. Честно говоря, я недоумеваю, каким образом однопоточный процесс может выиграть у многопоточного, когда в современных процессорах число логических ядер доходит до 24.
Решаемо через хранимые процедуры на LUA (можно реализовать почти что любой сложный SQL-запрос — вопрос лишь в вашем терпении).
Область применения у tarantool весьма специфичная, не предполагающая вот таких вот сложных use cases.
Ни в коем случае не покупайтесь на сравнения с реляционными СУБД. В лучшем случае tarantool можно сравнить с HandlerSocket в MySQL, где в «терминах грубой силы» победит MySQL (за счет multicore), а по гибкости однозначно tarantool.
С первого взгляда кажется логичным хранить точные значения персентилей с некоторым фиксированным значением (например с посекундным, т. е. p99 в течение секунды), а при построении графиков использовать max (или min по обстоятельствам) для вычисления y-координаты точки, в которую входит несколько интервалов.
Мне видится только один недостаток: нужно заранее определиться, какие персентили храним и рисуем.
>А мы это у себя реализовали в своих собственных внутренних проксях, через которые мы из любого кода ходим в Тарантул.
Что такого можно сделать во внешней проксе, чего нельзя сделать в коннекторе?

>У нас есть уже в 1.6 асинхронная репликация мастер-мастер
Дублирование запроса на соседа — это дублирование запросов на соседа. Репликация все-таки должна оставлять данные в консистентном состоянии.

>В 1.7 у нас будет синхронный мастер-мастер на основе RAFT.
Честно говоря, я не вполне понимаю вектор развития tarantool. То он позиционируется как «мемкеш на стеродидах», то как «lua application server». Судя по рекламе, которую вы даете в своих постах, это интересная наработка, которой мало кто пользуется, потому что не знают, как. Вы лучше определитесь с нишей, соберите набор best practices, дефолтные конфигурации для типовых задач, и т. д. Вот MySQL, сколько бы его ни ругали, используют повсеместно, потому что о нем полно информации.

>Вообще, если база почти целиком влезает в память, то все проще.
Кстати, а что делать, когда данные перестают влезать в один тарантул? Есть какие-то утилиты/гайды по шардингу или отдел эксплуатации каждый раз все заново изобретает?

>Если же у вас нет лишней памяти на page cache под весь индекс или индекс целиком не влезает в память
Я же писал, что можно параллельно cat'нуть индексный файл в /dev/null в некоторых случаях. И индекс всегда меньше данных. Взять, к примеру, базу постов хабра: реляционная база, хранящая только индексы по сообщениям и постам будет потреблять на это меньше памяти, чем tarantool, также хранящий в памяти тела сообщений.

>Хранение в RAM будет более экономной, потому что не надо много реплик (одна машина тарантула тянет такую же нагрузку как десятки машин с традиционными базами)
А можно с этого момента поподробнее? «Традиционные базы» могут использовать многоядерность современного железа и, как правило, успешно обрабатывают весьма нетривиальные запросы. Для простейших запросов по индексу у MySQL есть handlersocket, который в свое время позволял выжимать десятки тысяч запросов в секунду с одной железки. Более того, если база вдруг начинала «упираться в CPU», то можно было существенно все ускорить заменой железа: даешь больше ядер, получаешь лучшую производительность без каких-либо затрат на поддержку/разработку.
Это, кстати, весьма актуальный вопрос, т. к. я не нашел бенчмарков с простенькими луашками, которые делают, скажем, простенький left join для результата из одной записи.
А DELETE/UPDATE по вторичным индексам реализован в 1.6?
>Если машина падает, то нагрузка автоматом уходит на реплику.
Можно поподробнее с этого момента? Это встроенная возможность стандартного tarantool-коннектора, или вручную кодится в каждом клиенте? И если с SELECT-ами все понятно, то как быть с модифицирующими запросами в такой схеме? Как вы избегаете split brain-а при автоматических переключениях?

>Но давайте вспомним про традиционные базы данных (MySQL/Postgress), они прогревают кэши хорошо если со скоростью 1-3Mb/s
Откуда взята такая странная цифра? Традиционным базам нужно, чтобы индексы попали в page cache, что в некоторых случаях достижимо простым cat index.MYI > /dev/null на той же самой линейной скорости чтения.

>50% downtime на протяжении часов
Это как? Кроме того, разве в наше время такой downtime не решается установкой SSD для диска с данными? Будет ли хранение данных в RAM более экономным, чем использование SSD + «традиционная РСУБД»?
>у Tarantool есть режим hot standby, когда резервный сервер прямо на той же машине догоняется логами основного
Ценой 2x по памяти?

>Забудьте про JOIN в любой более-менее загруженном проекте
Согласен. Но ведь в любом проекте рано или поздно наступает момент сбора и подсчета продуктовой статистики, где SQL начинает блистать, предоставляя возможность очень просто конструировать и выполнять сложные запросы с агрегатными функциями, join-ами, группировкой и прочими плюшками. В таких задачах хочется гибкости, а не писать руками join/avg и прочее на каждый чих.

>В реальных задачах очень часто дешевле допустить некоторую избыточность, но при этом полностью избавиться от JOIN.
Зависит от задач. Денормализация подразумевает дублирование данных, а дублирование, как правило, идет рука об руку с рассинхронизацией. И не надо забывать, что в РСУБД данные не хранятся в памяти и проблема JOIN-ов на самом деле лежит в области seek-ов по диску. Странно, что в тарантуле, где все хранится прямо в локальной оперативной памяти, могут быть какие-то проблемы с подобными запросами. Однако согласен, JOIN + WHERE + ORDER BY для результата на десятки тысяч строк ни к чему хорошему и в оперативной памяти не приведет.

Что же касается планировщика и USING INDEX… Как правило, планировщик действительно лучше знает, какие индексы использовать в сложных запросах, USING INDEX был хорош в древние времена, дабы избегать filesort'ы. Очень странно, что проводя аналогию Tarantool — *SQL, вы замалчиваете, что любой запрос в тарантуле — это явный USING INDEX.

>Скажу лишь что в Tarantool можно добавлять и удалять таблички и индексы на лету.
А как выглядит добавление индекса на лету в однопоточном сервере?
Вы, конечно, очень радужно все описываете, однако какой как выглядит «холодный старт» тарантула? Я так понимаю, что ему необходимо прочитать с диска снапшот, затем проиграть «хвост» операций из журнала, затем перестроить индексы. И это все время полного простоя. Допустим, снапшот с нашими данными «весит» 80 гигабайт. Чтобы просто прочитать это с диска потребуется порядка 81920 / 200 ~ 409 секунд или почти 7 минут (200 mb/s вполне достойная скорость линейного чтения?). И это не какой-то «разогрев», когда «все тормозит». Это реальный 100%-й downtime.

Кстати, насчет сохранения снапшота: правильно ли я понял, что по факту нужен двойной объем RAM? Я так понимаю, что используется fork + COW, но ведь это может стрельнуть в самый неожиданный момент.

Да, а как быть со «сложными запросами», когда нужно использовать то один, то другой индекс, да еще дополнительно отфильтровывать результаты? Вы так настаиваете на сравнении с настоящими базами данных, что невольно хочется попросить предоставить кусок lua-процедуры, реализующий join в трех таблицах, где в where-условии также участвуют поля хотя бы из двух таблиц. Я представляю себе, как это выглядит, но не представляю человека, которому SELECT… FROM… JOIN… WHERE покажется сложнее, чем портянка аналогичного lua-кода.

Ну и напоследок: что у вас делают, когда в многогигабайтной расшардированной базе появляется необходимость делать выборку по новому полю? Как добавить индекс без простоя?
Рекомендую посмотреть в сторону intrinsic-ов: это почти прямое отражение mmx, sse и avx инструкций на «сишные функции». В итоге компилятор занимается подбором регистров, упорядочиванием и выравниванием команд, а программист говорит, что именно делать. В качестве бонуса получается некая «переносимость», т. к. intrinsics, в отличие от inline assembler'а, в различных компиляторах.
У Intel есть замечательный гайд: https://software.intel.com/sites/landingpage/IntrinsicsGuide/
1
23 ...

Information

Rating
Does not participate
Registered
Activity