Кэш и хэш в чем отличие
Перейти к содержимому

Кэш и хэш в чем отличие

  • автор:

Кэш на Хэш / From Cash to Hash или “Копи на трейдинг”

Крипто-ралли продолжается. Криптовалюты растут в цене, несмотря на попытки закручивания гаек со стороны правительств. Спрос на валюту “новой экономики” все еще превышает предложение.

Ландшафт рынка

В начале 2017 года проводилось большое количество ICO “технических” проектов. Вроде какого-нибудь “облачного суперкомпьютера на стероидах”. Разобраться в их сути обывателю довольно сложно. Вкладываться — рискованно. Понятно, что 95% таких проектов — скам. То есть не будут доведены до конца.

Сегодня рынок осознал, что для роста необходимо быть проще и ближе к частному инвестору. Текущий тренд: создание инвестиционных платформ, которые призваны помочь условному Джону Смиту просто и надежно вложить свои 100-1000-10 000$ в качественные криптоактивы.

Рассмотрим, какие у Джона есть варианты.

Самостоятельная торговля

Если вы — профессиональный инвестор и айтишник в одном лице — возможно, и лучший вариант.

Подходит, если у вас есть: а) технические и финансовые знания выше среднего; б) много свободного времени, чтобы анализировать рынок; в) самое главное — желание разбираться в ключах, настройках, газе, форках, “телеграмах”, скамах, “стаканах”.

Плюсы: все под контролем; ликвидность вложений (возможность в любой момент вывести деньги со счета)

Минусы: безопасность хранения средств; высокий риск ошибки при принятии инвестиционных решений; личное время.

Крипто-фонды

Хороший вариант, если вы: а) лично знаете создателей фонда и можете посмотреть им в глаза; б) уверены в них; в) готовы к дополнительным рискам выше среднего.

Фонды аккумулируют крупные суммы средств. Поэтому, во-первых, они становятся привлекательной добычей для хакеров. Такие случаи были. Во-вторых, могут совершать за счет вкладчиков нерыночные сделки, инвестируя в токены “дружественных” компаний. Вкладчики не могут влиять на то, что происходит в портфеле. Иногда это заканчивается плохо. Вообщем, как в старой прогнившей банковской системе. Только крипто-фонды никто не “спасет”. Они же децентрализованные.

Плюсы: удобство; возможность повышенного дохода за вложений в перспективные “монеты”, за которыми следят управляющие.

Минусы: на рынке высокая доля самозванцев без опыта портфельного управления; вы перечисляете деньги анонимным незнакомцам под честное слово и не можете контролировать их действия.

Копи-трейдинг, он же автоследование

Гибридный вариант. С одной стороны, торговый счет принадлежит инвестору. В отличие от крипто-фондов, инвестор всегда имеет доступ к счету и контролирует то, что на нем происходит.

С другой стороны, через платформу он получает доступ к торговым идеям от профессиональных управляющих. И их сделки автоматически повторяются на его счете.

Какой смысл профессиональным трейдерам делиться с инвесторами своими секретами? Ответ прост: они получают вознаграждение с прибыли с каждой успешной сделки. Для топовых управляющих суммарный капитал “последователей”-инвесторов может в разы превышать собственные средства. Для них это бизнес. Win-win.

Инвесторы могут выбирать среди сотен трейдеров, используя показатели доходности/риска, фильтры и рекомендации системы. Это как магазин управляющих для вашего счета. Можете выбрать нескольких. Можете поменять одного на другого.

Копи-трейдинг? И что. Ему уже сто лет в обед…

Естественно, сама по себе идея копи-трейдинга не нова. На форексе и фондовом рынке давно и успешно существуют десятки подобных сервисов.

Однако, новые технологии приносят новые возможности. Криптомир дает такому продукту новую жизнь.

Теперь в некоторых платформах инвесторы могут не только зарабатывать на трейдинге (или иногда не очень зарабатывать — тут уж, будем честными, как повезет), но и получать дополнительное вознаграждение как владельцы токенов самой платформы копи-трейдинга.

Как это работает. Платформа растет, новые инвесторы приходят, обороты увеличивается, платформа зарабатывает на комиссиях и делится ими со своими участниками.

К примеру, сервис Covesting имеет собственную внутреннюю валюту — cov (“ковы”). Вы можете вложить в успешного трейдера “ковы”. Все расчеты в рамках сервиса происходят также в “ковах”.

Чем больше инвесторов — тем выше спрос на “ковы”. Чем выше спрос — тем выше цена. Получается, что инвестор может заработать на платформе даже, даже если его торговля идет не очень хорошо. Это чем-то похоже на кэшбек для брокерских счетов.

По сути, covesting — пример создания специальной валюты для конкретной задачи. Для инвестирования. Курс этой валюты, сам, в свою очередь, формируется под влиянием спроса и (ограниченного объемом эмиссии!) предложения.

Хеш — что это такое и как хэш-функция помогает решать вопросы безопасности в интернете

Здравствуйте, уважаемые читатели блога KtoNaNovenkogo.ru. Хочу продолжить серию статей посвященных различным терминам, которые не всегда могут быть понятны без дополнительных пояснений. Чуть ранее я рассказывал про то, что значит слово кликбейт и что такое хост, писал про IP и MAC адреса, фишинг и многое другое.

Хеш-код

Сегодня у нас на очереди хеш. Что это такое? Зачем он нужен? Почему это слово так часто используется в интернете применительно к совершенно разным вещам? Имеет ли это какое-то отношение к хештегам или хешссылкам? Где применяют хэш, как вы сами можете его использовать? Что такое хэш-функция и хеш-сумма? Причем тут коллизии?

Все это (или почти все) вы узнаете из этой маленькой заметки. Поехали.

Что такое хеш и хэширование простыми словами

Слово хеш происходит от английского «hash», одно из значений которого трактуется как путаница или мешанина. Собственно, это довольно полно описывает реальное значение этого термина. Часто еще про такой процесс говорят «хеширование», что опять же является производным от английского hashing (рубить, крошить, спутывать и т.п.).

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

Для обычного человека это кажется белибердой, но как ни странно в наше время без хеширования практически невозможна работа в интернете. Так что же это такая за функция? На самом деле она может быть любой (приведенный выше пример это не есть реальная функция — он придуман мною чисто для вашего лучшего понимания принципа). Главное, чтобы результаты ее работы удовлетворяли приведенным ниже условиям.

Зачем нужен хэш

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

Если мы потом в исходном текстовом файле поменяем хотя бы одну букву или добавим лишний пробел, то повторно рассчитанный для него хэш уже будет отличаться от изначального (вообще другое число будет). Доходит, зачем все это нужно? Ну, конечно же, для того, чтобы понять, что файл именно тот, что и должен быть. Это можно использовать в целом ряде аспектов работы в интернете и без этого вообще сложно представить себе работу сети.

Где и как используют хеширование

Например, простые хэш-функции (не надежные, но быстро рассчитываемые) применяются при проверке целостности передачи пакетов по протоколу TCP/IP (и ряду других протоколов и алгоритмов, для выявления аппаратных ошибок и сбоев — так называемое избыточное кодирование). Если рассчитанное значение хеша совпадает с отправленным вместе с пакетом (так называемой контрольной суммой), то значит потерь по пути не было (можно переходить к следующему пакету).

А это, ведь на минутку, основной протокол передачи данных в сети интернет. Без него никуда. Да, есть вероятность, что произойдет накладка — их называют коллизиями. Ведь для разных изначальных данных может получиться один и тот же хеш. Чем проще используется функция, тем выше такая вероятность. Но тут нужно просто выбирать между тем, что важнее в данный момент — надежность идентификации или скорость работы. В случае TCP/IP важна именно скорость. Но есть и другие области, где важнее именно надежность.

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

Более сложные хеш-функции используются в криптографии. Главное условие для них — невозможность по конечному результату (хэшу) вычислить начальный (массив данных, который обработали данной хеш-функцией). Второе главное условие — стойкость к коллизиями, т.е. низкая вероятность получения двух одинаковых хеш-сумм из двух разных массивов данных при обработке их этой функцией. Расчеты по таким алгоритмам более сложные, но тут уже главное не скорость, а надежность.

Так же хеширование используется в технологии электронной цифровой подписи. С помощью хэша тут опять же удостоверяются, что подписывают именно тот документ, что требуется. Именно он (хеш) передается в токен, который и формирует электронную цифровую подпись. Но об этом, я надеюсь, еще будет отдельная статья, ибо тема интересная, но в двух абзацах ее не раскроешь.

Для доступа к сайтам и серверам по логину и паролю тоже часто используют хеширование. Согласитесь, что хранить пароли в открытом виде (для их сверки с вводимыми пользователями) довольно ненадежно (могут их похитить). Поэтому хранят хеши всех паролей. Пользователь вводит символы своего пароля, мгновенно рассчитывается его хеш-сумма и сверяется с тем, что есть в базе. Надежно и очень просто. Обычно для такого типа хеширования используют сложные функции с очень высокой криптостойкостью, чтобы по хэшу нельзя было бы восстановить пароль.

Какими свойствами должна обладать хеш-функция

Хочу систематизировать кое-что из уже сказанного и добавить новое.

  1. Как уже было сказано, функция эта должна уметь приводить любой объем данных (а все они цифровые, т.е. двоичные, как вы понимаете) к числу заданной длины (по сути это сжатие до битовой последовательности заданной длины хитрым способом).
  2. При этом малейшее изменение (хоть на один бит) входных данных должно приводить к полному изменению хеша.
  3. Она должна быть стойкой в обратной операции, т.е. вероятность восстановления исходных данных по хешу должна быть весьма низкой (хотя последнее сильно зависит от задействованных мощностей)
  4. В идеале она должна иметь как можно более низкую вероятность возникновения коллизий. Согласитесь, что не айс будет, если из разных массивов данных будут часто получаться одни и те же значения хэша.
  5. Хорошая хеш-функция не должна сильно нагружать железо при своем исполнении. От этого сильно зависит скорость работы системы на ней построенной. Как я уже говорил выше, всегда имеется компромисс между скорость работы и качеством получаемого результата.
  6. Алгоритм работы функции должен быть открытым, чтобы любой желающий мог бы оценить ее криптостойкость, т.е. вероятность восстановления начальных данных по выдаваемому хешу.

Хеш — это маркер целостности скачанных в сети файлов

Где еще можно встретить применение этой технологии? Наверняка при скачивании файлов из интернета вы сталкивались с тем, что там приводят некоторые числа (которые называют либо хешем, либо контрольными суммами) типа:

CRC32: 7438E546 MD5: DE3BAC46D80E77ADCE8E379F682332EB SHA-1: 332B317FB97126B0F79F7AF5786EBC51E5CC82CF

Что это такое? И что вам с этим всем делать? Ну, как правило, на тех же сайтах можно найти пояснения по этому поводу, но я не буду вас утруждать и расскажу в двух словах. Это как раз и есть результаты работы различных хеш-функций (их названия приведены перед числами: CRC32, MD5 и SHA-1).

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

После чего прогнать скачанные файлы через эту программку и сравнить полученные числа с приведенными на сайте. Если совпадают, то сбоев при скачивании не было, а если нет, то значит были сбои и есть смысл повторить закачку заново.

Популярные хэш-алгоритмы сжатия

  1. CRC32 — используется именно для создания контрольных сумм (так называемое избыточное кодирование). Данная функция не является криптографической. Есть много вариаций этого алгоритма (число после CRC означает длину получаемого хеша в битах), в зависимости от нужной длины получаемого хеша. Функция очень простая и нересурсоемкая. В связи с этим используется для проверки целостности пакетов в различных протоколах передачи данных.
  2. MD5 — старая, но до сих пор очень популярная версия уже криптографического алгоритма, которая создает хеш длиной в 128 бит. Хотя стойкость этой версии на сегодняшний день и не очень высока, она все равно часто используется как еще один вариант контрольной суммы, например, при скачивании файлов из сети.
  3. SHA-1 — криптографическая функция формирующая хеш-суммы длиной в 160 байт. Сейчас идет активная миграция в сторону SHA-2, которая обладает более высокой устойчивостью, но SHA-1 по-прежнему активно используется хотя бы в качестве контрольных сумм. Но она так же по-прежнему используется и для хранения хешей паролей в базе данных сайта (об этом читайте выше).
  4. ГОСТ Р 34.11-2012 — текущий российский криптографический (стойкий к взлому) алгоритм введенный в работу в 2013 году (ранее использовался ГОСТ Р 34.11-94). Длина выходного хеша может быть 256 или 512 бит. Обладает высокой криптостойкостью и довольно хорошей скоростью работы. Используется для электронных цифровых подписей в системе государственного и другого документооборота.

HashTab — вычисление хеша для любых файлов на компьютере

Раз уж зашла речь о программе для проверки целостности файлов (расчета контрольных сумм по разным алгоритмам хеширования), то тут, наверное, самым популярным решением будет HashTab.

Она бесплатна для личного некоммерческого использования и покрывает с лихвой все, что вам может понадобиться от подобного рода софта. После ее скачивания и установки запускать ничего не надо. Просто кликаете правой кнопкой мыши по нужному файлу в Проводнике (или ТоталКомандере) и выбираете самый нижний пункт выпадающего меню «Свойства»:

Как узнать хеш файла

В открывшемся окне перейдите на вкладку «Хеш-суммы файлов», где будут отображены контрольные суммы, рассчитанные по нужным вам алгоритмам хэширования (задать их можно нажав на кнопку «Настройки» в этом же окне). По умолчанию отображаются три самых популярных:

Хеш-суммы файлов в программе HashTab

Чтобы не сравнивать контрольные суммы визуально, можно числа по очереди вставить в рассположенное ниже поле (со знаком решетки) и нажать на кнопку «Сравнить файл».

Как видите, все очень просто и быстро. А главное эффективно.

Удачи вам! До скорых встреч на страницах блога KtoNaNovenkogo.ru

Эта статья относится к рубрикам:

  • �� Binance — лучшая криптобиржа в мире
  • �� Эксмо — лучшая криптобиржа в рунете
  • ⛏ ВоркЗилла — удаленная работа для всех
  • �� Etxt — платят за написание текстов
  • ✍ Кьюкоммент — биржа комментариев
  • �� 60сек — выгодный обмен криптовалют
  • �� Вктаргет — заработок в соцсетях
  • �� Смотреть все.

Комментарии и отзывы (6)

Душевная благодарность за информацию ! Долго искал портативную версию, теперь установил по указанной ссылке, в «Настройках» отметил «популярные» — всё работает, думаю, что проблемные «закачки» теперь можно будет установить сразу после завершения процесса

Спасибо за столь объемную (много разных тем затрагивающую) статью и понятно описано

Я совсем далек от таких подробностей(музыкант),но начал читать и кажется продолжу свой ликбез.

Спасибо за труд!

Как же тогда взламывают пароли, да и просто похищают, если такая система стоит на страже? Значит можно всё взломать и похитить.

Ваш комментарий или отзыв

Кэш, хэш и няш-меш

UPD0 (2016-07-19 23-31): судя по всему, первая половина моей статьи — успешно изобретённый велосипед. Спасибо хабравчанам за ссылку на спецификацию
Статья ценна не более, чем вольное описание уже придуманной технологии.

Предыстория

Июльский субботний вечер подходил к концу. Нарубив дров на шашлык, я повесил USB-модем на багету, скомандовал sudo wvdial , развернул браузер и обновил вкладку с открытым гитхабом. Вернее, попытался обновить. Скорость не радовала, и в итоге страница-то обновилась, но явно не хватало какого-то из стилевых файлов; и дело было не в блокировке, поскольку аналогичные проблемы я наблюдал и с другими сайтами, и зачастую они решались просто многократным обновлением страницы. Во всём был виноват перегруз 3G-сети.

Стоп! А как же кэш?

Недолгое гугление привело на официальный гугловский мануал. Целиком пересказывать его не буду; скорее всего, дело было в том, что браузер прилежно ждал, когда сервер передаст ETags, а ответ сервера затерялся в переполненных триджунглях.

Через пару дней, возвращаясь душным днём из кафе, я придумал рацпредложение, которое решает эту (и несколько других проблем), которое и излагаю в данной статье.

Суть предложения

Добавить ко всем тэгам для подключения подчинённой статики (стилей, скриптов, изображений) атрибут checksum , который бы хранил хэш (например, SHA-1, как в git) требуемого файла:

Найдя в теле веб-страницы подобный тэг, браузер смотрит, есть ли объект с таким хэшем в кэше, и если есть, то не отправлять никаких запросов вообще: и так понятно, что файл — ровно тот, который требуется. Файлы в кэше браузера лучше сразу хранить с именами, соответствующими их хэшам, как это делает тот же git.

Обратная совместимость предлагаемого решения очевидна.

Какие проблемы это решает?

Пресловутая угадайка: актуален ли файл в кэше?

  • Больше не нужно отправлять запрос и сличать полученные ETags.
  • Даже если файл в кэше вроде как устарел, но хэш совпадает — его можно смело использовать.
  • Чистка кэша как средство решения проблем частично теряет актуальность.

Дилемма: jQuery со своего домена или с CDN?

Владельцам малых сайтов часто приходится выбирать: либо подключать jQuery и/или подобные ей библиотеки с CDN (гугловского, например), или со своего домена.
В первом случае уменьшается время загрузки сайта (в том числе первичной, т.е. при первом заходе посетителя на сайт) за счёт того, что файл с серверов Гугла с большой долей вероятности уже есть в кэше браузера. Но, например, разработчики WordPress придерживаются второго варианта, ставя во главу угла автономность. И в условиях, когда CDN падают, блокируются и т.д., их можно понять.
Теперь от такой проблемы можно будет избавиться навсегда: не всё ли равно, откуда получен файл, если его содержимое — это ровно то, что нужно html-странице, и она это удостоверяет? Можно смело указывать свой домен, и если библиотека есть в кэше (неважно, загруженная с этого сайта, другого «малого» сайта или из какого-нибудь CDN) — она подхватится.

Смешанный HTTPS/HTTP-контент

Одна из причин запрета загрузки HTTP-ресурсов на HTTPS-страницах — возможность подмены HTTP-контента. Теперь это больше не преграда: браузер может получить требуемый контент и сверить его хэш с хэшем, переданным по HTTP. Отмена запрета на смешанный контент (при наличии и совпадении хэша) позволит ускорить распространение HTTPS.

Косвенное определение истории по времени загрузки статики

Известно, что владелец некоторого сайта evilsite.org может (с некоторой долей вероятности) определить, был ли посетитель на другом сайте goodsite.org , запросив, например, изображение goodsite.org/favicon.ico . Если время загрузки иконки ничтожно мало — то она в кэше, следовательно, посетитель был на сайте goodsite.org . Теперь эта атака усложнится: околонулевое время отклика будет лишь обозначать, что посетитель был на сайте с таким же фавиконом. Это, конечно, не решает проблему целиком, но всё же несколько усложняет жизнь определяющему.

На что это не влияет?

  • На html-страницы
  • На изображения, стили и скрипты, открываемые по непосредственной ссылке, а не служащие вспомогательными элементами страницы.
  • На изображения, стили и скрипты, которые не предполагаются неизменными, например, когда подключается самая новая версия некоторой библиотеки с CDN этой библиотеки.

Идеология

Как обычно (математик я, что уж тут поделать) сформулируем аксиомы, которые вкладываются в предложение:

  1. Все передаваемые файлы делятся на главные (в основном html-страницы) и подчинённые (скрипты, изображения, стили и т.д.).
    В идеологии, заложенной в стандарты HTTP-кэширования, все файлы равноправны. Это, конечно, толерантно, но не отвечает современным реалиям.
  2. Неважно, откуда получен подчинённый файл. Важно, что его содержимое удовлетворяет нужды главного.
    В существующей идеологии даже сама аббревиатура URI — Uniform Resource Identifier — предполагает, что идентификатором ресурса является его адрес в сети. Но, увы, для подчинённых файлов это несколько не соответствует действительности.

Перспективы

Обещанный няш-меш

Зная хэш требуемого вспомогательно файла, можно почти смело запрашивать его у кого угодно; основная опасность: если опрашиваемый узел действительно имеет требуемый файл, то он знает его содержимое и, скорее всего, как минимум один URI-адрес, по которому требуемый файл может (или мог) быть получен. Имеем два варианта использования предлагаемой технологии с учётом этой угрозы с целью плавного подхода к няш-меш сети:

Доверенные устройства

Например, в офисе работают программисты, ЭВМ которых объединены в локальную сеть. Программист Вася приходит рано утром, открывает гитхаб и получает в кэш стили от нового дизайна, который выкатили ночью (у нас — ночь, там — день). Когда в офис приходит программист Петя и тоже загружает html-код гитхабовской странички, его ЭВМ спрашивает у всех ЭВМ в сети: «А нет ли у вас файла с таким-то хэшем?» «Лови!» — отвечает Васина ЭВМ, экономя тем самым трафик.
Потом наступает перерыв, Вася и Петя лезут смотреть котиков и пересылают фотографии друг другу. Но каждый котик скачивается через канал офиса только один раз.

Анонимный разделяемый кэш

Аня едет в трамвае с работы и читает новости… например, на Яндекс-Новостях. Встретив очередной тэг , Анин телефон со случайного MAC-адреса спрашивает всех, кого видит: «Ребят, а ни у кого нет файла с таким-то хэшем?». Если ответ получен в разумное время — профит, Аня сэкономила недешёвый мобильный трафик. Важно почаще менять MAC-адрес на случайный да не «орать», когда в поле видимости слишком мало узлов и спрашивающего можно идентифицировать визуально.
Разумность времени ответа определяется исходя из стоимости трафика.

Дальнейший переход к няш-мешу

Фотография в соцсети может быть представлена как блоб, содержаший хэш и адрес собственно изображения (возможно, в нескольких различных размерах), а также список комментариев и лайков. Этот блоб тоже можно рассматривать как вспомогательный файл, кэшировать и передавать друг другу.
Более того, альбом фотографий тоже легко превращается в блоб: список хэшей изображений + список хэшей блобов-фотографий (первое нужно, чтобы при добавлении лайка/комментария показывать фотографии сразу, а метаинформацию — по мере её получения).
Останется только реализовать электронную подпись и поля вида «замещает блоб такой-то» — и готова няш-меш-социалочка.

Компактизация хэша

В идеале при записи хэша следует использовать не шестнадцатеричную систему счисления, а систему с бОльшим основанием (раз уж мы взялись экономить трафик). Ещё одна идея — атрибут magnet , содержащий magnet-ссылку. Дёшево, сердито, стандартизировано и позволяет указывать также несколько классических адресов источников, что бывает немаловажно в случае ковровых блокировок и в случаях, когда браузеру известно, что трафик к различным серверам тарифицируется по-разному.

Поведение при несовпадении

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

Файлы-альтернативы

В некоторых случаях можно использовать любой из нескольких файлов с разными хэшами. Например, на сайте используется минифицированная jQuery, но если в кэше браузера есть неминифицированная — что мешает использовать её?

Превентивное кэширование

Многие устройства работают в двух режимах: когда интернет условно-безлимитен (например, мобильный телефон в вай-фай сети) и когда интернет ограничен (лимит по трафику или узкий канал). Браузер или расширение к нему может, пользуясь безлимитным подключением, заранее скачивать популярные библиотеки (наподобие jQuery и плагинов к ней), также по мере необходимости их обновлять. Это ли не мечта многих, чтобы jQuery была включена в браузер?

Заключение

Выдвигаемое рацпредложение актуально, так как борьба за оптимизацию загрузки сайтов идёт полным ходом. Более всего выиграют малые и средние сайты за счёт разделяемых библиотек (и, может быть, некоторых часто используемых изображений) в кэше. Уменьшится потребление трафика мобильными устройствами, что важно с учётом ограниченной пропускной способности каналов сотового интернета. Крупные сайты также могут уменьшить нагрузку на свои серверы в случае, если будут внедрены mesh-технологии.
Таким образом, поддержка предлагаемой технологии выгодна и вебмастерам, чьи сайты будут грузиться быстрее, и производителям браузеров, которые тоже будут быстрее отображать страницы, и провайдерам, у которых уменьшится потребление полосы (пусть и не столь значительно, но от провайдеров активных действий и не требуется).

P.S.
Мне было бы очень приятно услышать мнение Mithgol, Shpankov и BarakAdama.

P.P.S.
Хабр всезнающий, в какое спортлото отправлять рацпредложение?

Хеш+кэш: оптимизация «потоковой» обработки

Что делать, если в базу хочется записать массу «фактов» много большего объема, чем она способна выдержать? Сначала, конечно, приводим данные к более экономичной нормальной форме и получаем «словари», в которые будем писать однократно. Но как это делать наиболее эффективно?

Именно с таким вопросом мы столкнулись при разработке мониторинга и анализа логов серверов PostgreSQL, когда остальные способы оптимизации записи в БД оказались исчерпаны.

Сразу оговоримся, что наши коллекторы работают под управлением Node.js, поэтому с процессорными регистрами и кэшами мы никак не взаимодействуем. А вариант использования «стораджей» или внешних кэширующих сервисов/БД дает слишком большие задержки при входящих потоках в несколько сотен Mbps.

Поэтому мы стараемся кэшировать все в RAM, конкретно — в памяти JavaScript-процесса. Про то, как эффективнее это организовать, и пойдет речь дальше.

Кэширование наличия

Наша основная задача — сделать так, чтобы в БД попал по возможности единственный экземпляр какого-либо объекта. Такими у нас выступают многократно повторяющиеся оригинальные тексты SQL-запросов, шаблоны планов их выполнения, узлов этих планов — короче, какие-то текстовые блоки.

Исторически так сложилось, что в качестве идентификатора мы использовали UUID -значение, которое получали в результате прямого вычисления MD5-хеша от текста объекта. После этого проверяем наличие такого хеша в локальном «словаре» в памяти процесса, и вот если его там нет — только тогда пишем в БД в «словарную» таблицу.

То есть само оригинальное текстовое значение нам хранить не требуется (а иногда оно занимает десятки килобайт) — достаточно всего лишь самого факта наличия соответствующего хеша в словаре.

Словарь ключей

Такой словарь можно вести в Array , и использовать Array.includes() для проверки наличия, но это достаточно избыточно — поиск деградирует (по крайней мере, в предыдущих версиях V8) линейно от размера массива, O(N). Да и в современных реализациях, несмотря на все оптимизации, проигрывает по скорости 2-3%.

Поэтому в эпоху до ES6 традиционным решением было хранение Object , ключами которого выступали хранимые значения. А вот значениями ключей каждый назначал что хотел — например, Boolean :

var dict = <>; function has(key) < return dict[key] !== undefined; >function add(key)

Но вполне очевидно, что мы тут явно храним лишнее — то самое значение ключа, которое никому не нужно. А что если его — вообще не хранить? Так и появился объект Set.

Тесты показывают, что поиск с помощью Set.has() быстрее примерно на 20-25%, чем проверка ключа в Object . Но это не единственное его преимущество. Раз мы храним меньше, то и памяти нам должно требоваться меньше — а это впрямую сказывается на производительности, когда речь идет о сотнях тысяч таких ключей.

Итак, Object , в котором находится 100 UUID-ключей в текстовом представлении, занимает в памяти 6216 байт:

Set с тем же содержимым — 2632 байта:

То есть Set работает быстрее и при этом занимает в 2.5 раза меньше памяти — победитель очевиден.

Оптимизируем хранение UUID-ключей

Вообще, в природе распределенных систем UUID-ключи достаточно распространены — у нас в СБИСе они, как минимум, применяются для идентификации документов и регламентов в электронном документообороте, персон в обмене сообщениями,…

Давайте теперь еще раз внимательно посмотрим на картинку выше — каждый UUID-ключ, хранимый в hex-представлении, «стоит» нам 56 байт памяти. Но у нас их — сотни тысяч, поэтому резонно спросить: «А меньше — можно?»

Для начала вспомним, что UUID — это 16-байтовый идентификатор. По сути, кусок бинарных данных. А для передачи по email, например, двоичные данные кодируются в base64 — попробуем его применить:

let str = Buffer.from(uuidstr, 'hex').toString('base64');

Уже по 48 байт — лучше, но неидеально. Давайте попробуем перевести шестнадцатиричное представление прямо в строку:

let str = Buffer.from(uuidstr, 'hex').toString('binary');

Вместо 56 байт на каждый ключ — 40 байт, экономия почти 30%!

Master, worker — где хранить словари?

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

Однако существенная доля времени мастера тратилась на channel.onread — то есть на обработку получения пакетов со «словарной» информацией от дочерних процессов:

Двойной Set-барьер от записи

Теперь на секунду задумаемся — воркеры шлют и шлют мастеру одни и те же словарные данные (в основном — это шаблоны планов и повторяющиеся тела запросов), он их в поте лица парсит и… ничего не делает, потому что они в БД уже были отправлены раньше!

Так если мы Set -словариком «защитили» базу от повторной записи из мастера, почему бы не применить тот же подход для «защиты» мастера от передачи из воркера.

Собственно, что и было сделано, и сократило втрое прямые издержки на обслуживание канала обмена:

Но ведь теперь воркеры делают вроде как больше работы — хранят словари и фильтруют по ним? Или нет. На самом деле, работать они стали существенно меньше, поскольку сама передача больших объемов (даже по IPC!) — это не дешево.

Приятный бонус

Поскольку мастер теперь стал принимать гораздо меньший объем информации, то и памяти под эти контейнеры стал выделять гораздо меньше — а, значит, затраты времени на работу Garbage Collector’а сильно снизились, что положительно повлияло на latency системы в целом.

Такая схема обеспечивает защиту от повторных записей на уровне коллектора, но что делать, если у нас несколько коллекторов? Тут поможет только триггер с INSERT . ON CONFLICT DO NOTHING .

Ускоряем вычисление хешей

В нашей архитектуре весь поток логов с одного сервера PostgreSQL обрабатывает один воркер.

То есть один сервер — это одна задача на воркере. При этом загрузка воркеров балансируется назначением задач-серверов так чтобы потребление CPU воркерами всех коллекторов было примерно одинаковым. Этим занимается отдельный сервис диспетчера.

«В среднем» каждый воркер обрабатывает несколько десятков задач, которые дают примерно одинаковую суммарную нагрузку. Однако, есть сервера, которые по количеству записей в логе значительно превосходят остальные. И даже в том случае, если диспетчер оставляет эту задачу единственной на воркере, его загрузка сильно выше остальных:

Сняли CPU-профайл этого воркера:

image

На верхних строках — вычисление MD5-хешей. А их действительно вычисляется огромное количество — для всего потока входящих объектов.

xxHash

Как оптимизировать эту часть, если не считать эти хеши мы не можем?

Решили попробовать другую хеш-функцию — xxHash, реализующую Extremely fast non-cryptographic hash algorithm. И модуль для Node.js — xxhash-addon, который использует свежую версию библиотеки xxHash 0.7.3 с новым алгоритмом XXH3.

Проверим, прогнав каждый вариант на наборе строк разной длины:

const crypto = require('crypto'); const < XXHash3, XXHash64 >= require('xxhash-addon'); const hasher3 = new XXHash3(0xDEADBEAF); const hasher64 = new XXHash64(0xDEADBEAF); const buf = Buffer.allocUnsafe(16); const getBinFromHash = (hash) => buf.fill(hash, 'hex').toString('binary'); const funcs = < xxhash64 : (str) =>hasher64.hash(Buffer.from(str)).toString('binary') , xxhash3 : (str) => hasher3.hash(Buffer.from(str)).toString('binary') , md5 : (str) => getBinFromHash(crypto.createHash('md5').update(str).digest('hex')) >; const check = (hash) => < let log = []; let cnt = 10000; while (cnt--) log.push(crypto.randomBytes(cnt).toString('hex')); console.time(hash); log.forEach(funcs[hash]); console.timeEnd(hash); >; Object.keys(funcs).forEach(check); 

Результаты:

xxhash64 : 148.268ms xxhash3 : 108.337ms md5 : 317.584ms 

Как и ожидалось, xxhash3 оказался намного быстрее MD5!

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

Подмена хешей

Но просто взять и поменять в таблицах-словарях старые UUID-поля на новый хеш мы не можем — ведь и база, и существующий frontend ждут, что объекты продолжат идентифицироваться по UUID.

Поэтому добавим в коллекторе еще один кэш — для уже посчитанных MD5. Теперь это будет Map, в котором ключи — xxhash3, значения — MD5. Для одинаковых строк мы не пересчитываем заново «дорогой» MD5, а берем его из кэша:

const getHashFromBin = (bin) => Buffer.from(bin, 'binary').toString('hex'); const dictmd5 = new Map(); const getmd5 = (data) => < const hash = xxhash(data); let md5hash = dictmd5.get(hash); if (!md5hash) < md5hash = md5(data); dictmd5.set(hash, getBinFromHash(md5hash)); return md5hash; >return getHashFromBin(md5hash); >; 

Снимаем профайл — доля времени вычисления хешей заметно снизилась, ура!

Так что теперь мы считаем xxhash3, затем проверяем кэш MD5 и получаем искомый MD5, а затем проверяем кэш словаря — если там этого md5 нет, то отправляем на запись в БД.

Что-то слишком много проверок… Зачем проверять кэш словаря, если уже проверили кэш MD5? Выходит, все кэши словарей теперь не нужны и достаточно иметь всего один кэш — для MD5, с которым и будут производиться все основные операции:

В итоге, мы заменили проверку в нескольких кэшах «объектных» словарей одним кэшем MD5, а ресурсоемкую операцию расчета MD5-хеша выполняем только для новых записей, используя для входящего потока гораздо более эффективный xxhash.

Спасибо Kilor за помощь в подготовке статьи.

  • Блог компании Тензор
  • Высокая производительность
  • JavaScript
  • Серверная оптимизация
  • Node.JS

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *