...

суббота, 7 января 2017 г.

[Перевод] Малоизвестные Git-команды

У Git есть строгие обязательства по обратной совместимости: многие продвинутые возможности скрыты за разнообразными опциями, а не применяются как поведение по умолчанию. К счастью, Git также поддерживает и алиасы, так что вы можете создавать свои собственные команды, которые делают всю характерную для Git магию. Под катом — подборка полезных (или как минимум забавных) алиасов, определённых в моём .gitconfig.

git please


$ git config --global alias.please 'push --force-with-lease'

Каждому разработчику приходилось хотя бы раз общаться со своим тимлидом на тему принудительного пуша (force pushing) в общую ветку (не делайте этого). Ребейз (rebasing), внесение правок и squash — всё это забавно до тех пор, пока вы не перезапишете часть общей истории и не раскидаете дублирующиеся коммиты по всему репозиторию. К счастью, Git не позволит вам невольно перезаписать историю на сервере. Вам придётся явным образом передать в git push опцию --force, чтобы доказать серьёзность своих намерений. Но принудительный пуш — это грубый подход: вы затаптываете локальной версией вышерасположенную ветку, и все изменения, которые вы к тому моменту не подтянули (fetch), будут стёрты из истории.

Git-опция --force-with-lease действует гораздо аккуратнее: она проверяет, чтобы ваша локальная копия ref’а была самой свежей, прежде чем накатить её. Это означает, что вы как минимум подтянули все изменения, которые собираетесь затоптать. Но чтобы не писать каждый раз git push --force-with-lease, я сделал для этой строки алиас: git please

git commend


$ git config --global alias.commend 'commit --amend --no-edit'

Бывало так, что вы закоммитили и тут же сообразили, что забыли проиндексировать (stage) файл? Больше не нужно об этом беспокоиться! Алиас git commend тихо прикрепляет к последнему созданному вами коммиту все проиндексированные файлы, повторно используя уже имеющееся сообщение о коммите.
$ git add Dockerfile
$ git commit -m ‘Update Bitbucket pipeline with new Docker image’
# (facepalm)
$ git add bitbucket-pipelines.yml
$ git commend

git it


$ git config --global alias.it \
'!git init && git commit -m “root” --allow-empty'

Первому коммиту в репозитории нельзя сделать ребейз, как обычному. Поэтому рекомендуется в качестве корневого создавать пустой коммит. Алиас git it инициализирует ваш репозиторий и за одну операцию создаёт пустой корневой коммит. И когда вы в следующий раз запустите проект, то не надо просто добавлять его в систему управления версиями: выполните git it!
$ cd shiny-new-thing
$ git it
Initialized empty Git repository in /shiny-new-thing/.git/
[master (root-commit) efc9119] root

git staaash


$ git config --global alias.stsh 'stash --keep-index'
$ git config --global alias.staash 'stash --include-untracked'
$ git config --global alias.staaash 'stash --all'

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

Я сделал несколько удобных алиасов для разных вариантов git stash, в зависимости от того, какие биты вашего рабочего дерева нужно скрыть:

git stsh      # скрывает только непроиндексированные изменения в отслеживаемых файлах
git stash     # скрывает все изменения в отслеживаемых файлах 
git staash    # скрывает неотслеживаемые и отслеживаемые файлы
git staaash   # скрывает игнорируемые, неотслеживаемые и отслеживаемые файлы

Если сомневаетесь в выборе, то самый длинный алиас (git staaash) всегда сможет восстановить рабочее дерево состояния свежего клона вашего репозитория.

git shorty


$ git config --global alias.shorty 'status --short --branch'

Я запускаю git status чаще любой другой Git-команды. Встроенная помощь в Git за последние годы стала куда удобнее, что очень хорошо для начинающих, но для более опытных пользователей информация слишком многословна. Например, git status объясняет мне в 12 строках, что у меня пара индексированных, неиндексированных и неотслеживаемых изменений:
$ git status
On branch master
Changes to be committed:
  (use “git reset HEAD <file>…” to unstage)
    modified: package.json
Changes not staged for commit:
  (use “git add <file>…” to update what will be committed)
  (use “git checkout -- <file>…” to discard changes)
    modified: package.json
Untracked files:
  (use “git add <file>…” to include in what will be committed)
    index.js

Всё то же самое git shorty говорит мне тремя строками:
$ git shorty
## master
AM test
?? .gitignore

Для краткости я сделал это в виде алиаса git st, не смог остановиться.

git merc


$ git config --global alias.merc 'merge --no-ff'

Если вы используете обычный рабочий процесс ветвления без ребейза, то будет не лучшим решением запускать стандартный git merge для слияния веток с фичами с мастер-веткой. Если не добавить к этой команде опции, то по умолчанию станет использоваться стратегия слияния --ff, при которой новый коммит слияния будет создан только в том случае, если в мастер-ветке нет новых изменений. В противном случае мастер-ветка просто «перемотается» до места последнего коммита в вашей ветке. Лишь иногда, создавая коммит слияния, при просмотре Git-истории бывает непросто сказать, какой код был разработан в какой ветке.

git merc использует стратегию --no-ff, при которой всегда создаётся коммит слияния.

Между прочим, --no-ff всегда используется по умолчанию в ходе слияния pull request’ов в Bitbucket.

git grog


$ git config --global alias.grog 'log --graph --abbrev-commit --decorate --all --format=format:"%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(dim white) - %an%C(reset) %C(bold green)(%ar)%C(reset)%C(bold yellow)%d%C(reset)%n %C(white)%s%C(reset)"'

Мой алиас git grog (или graphical log) в последние годы разросся настолько, что я больше не уверен, будто точно знаю, что он делает. Но выглядит красиво:

git grog

Для сравнения, вот стандартный git log:

git log

Там доступны все виды удобных форматов, так что форкайте вышеуказанную команду и пользуйтесь на здоровье!

Для поклонников GUI


Если вы поклонник Git GUI и работаете под Mac или Windows, то, возможно, вы используете наш бесплатный Git-клиент Atlassian SourceTree. Если да, то примените описанные в этой статье алиасы, создав новое кастомное действие — можно назначить комбинацию клавиш — в настройках SourceTree:

Это действие запускается с помощью меню (Actions -> Custom Actions) или клавиатурной комбинации:

Приятного алиасинга!

Комментарии (0)

    Let's block ads! (Why?)

    Пошаговая инструкция: сборка JDK9 из исходников на Windows 10

    В последнее время со сборкой JDK в Windows всё стало хорошо и приятно, поэтому поделюсь радостью и распишу, как это делается.

    Каждый второй, кто пытается собрать что-то под Windows, получет глубокую психологическую травму, и заранее ожидает от сборки следующих эмоций:

    Что касается JDK, если не сходить с пряничной дорожки, делать в точности как в этой инструкции, проблем не будет. Возможные проблемы обозначены в тексте.

    Общий смысл происходящего: устанавливаем компиляторы (JDK8, Visual Studio 2013), среду сборки (GNU/Cygwin) и набор стандартных пакетов для неё, собираем из исходников Freetype, заливаем репозиторий JDK, configure, make, java -version.

    Мы будем собирать Java и C++ (раз вы читаете эту статью, то, наверное, уже в курсе), поэтому на микроволновке лучше сборкой не заниматься. Нужна рабочая станция или ноутбук с нормальным процессором, и, желательно, SSD вместо жесткого диска для сборочной директории проекта. Кроме сборки, какое-то время потратится на скачивание исходника и установку Visual Studio.

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

    1. Устанавливаем JDK8

      для бута.

      Ссылка на загрузку:
      http://ift.tt/1h8zgnv

    2. Устанавливаем Visual Studio 2013

      (версия Express подойдёт).

      Ссылка на загрузку:
      http://ift.tt/2i3TuZf

      Если вы устанавливаете полную версию, то при установке вам дадут выбор компонентов: достаточно установить только те компоненты, которые относятся к C++ и Windows SDK.

      При установке Express, никакого выбора не будет — к счастью, оно само устанавливает именно то, что нам нужно. Это выглядит как-то так:



      После установки, обязательно нужно перезагрузить операционную систему.

      Важно: нужно установить именно Visual Studio 2013.
      Не ниже потому, что о версии 2013 говорится в Build Readme.
      Не выше потому, что если попробовать провести сборку с установленной Visual Studio 2015, то сборщик JDK будет видеть компилятор, но будет ломаться с ошибкой:
      C compiler cannot create executables
      Если заглянуть в config.log, становится понятна причина:
      LINK : fatal error LNK1104: cannot open file 'LIBCMT.lib'
      Если тупо сделать
      export LINK="/NODEFAULTLIB:libcmt.lib"
      то оно развалится:
      unresolved external symbol mainCRTStartup.

      Если кто-то в комментариях знает, как безболезненно починить эту ошибку и запуститься на 2015, буду очень благодарен. Неприятно быть залоченным на устаревшую версию компилятора, даже если она бесплатная.

    3. Устанавливаем Cygwin.


      Ссылка на загрузку: www.cygwin.com

      Важно: сейчас принято использовать msys2 вместо Cygwin.
      К сожалению, сборка JDK тут же упадет с ошибкой:
      configure: error: /usr/bin/bash /x/git/openjdk9/common/autoconf/build-aux/config.sub x86_64-pc-msys failed
      Если попытаться прописать msys так же, как там прописан Cygwin, то ошибка меняется:
      unsupported operating system msys
      Если какой-нибудь герой в комменатриях расскажет, как правильно прописать msys, это было бы здорово.

    4. Устанавливаем пакеты для Cygwin

      , описанные в Build Readme.

      В скобках указана категория пакета, после знака "—" ради чего мы это ставим.
      Назначение каждого экзешника можно почитать в мане, но чтобы собрать этого знать не нужно.

      • binutils (devel) – ar.exe
      • make (devel) — make.exe
      • m4 (interpreters) — m4.exe
      • cpio (utils) — cpio.exe
      • gawk (base, interpreters) — gawk.exe
      • file (base) — file.exe
      • zip (archive) — zip.exe
      • unzip (archive) — unzip.exe
      • procps-ng (system) — free.exe

      Для возмущенных таким большим набором зависимостей — скажите спасибо, что не заставили устанавливать Python и Ruby! :)

      Для тех, кто ни разу не сталкивался с Cygwin пара замечаний:

      • Установка пакетов выглядит как-то так:

      • Существует множество пакетов, например, со словом binutils в названии.
        Нужно выбирать пакет, в точности по буквам совпадающий с названием из списка, соответствующий группе из списка. (Конечно, если вы точно знаете что делаете, ваша воля :) )
      • Принадлежность пакетов к группам в Cygwin время от времени меняется. В частности, группы, перечисленные в этом списке уже не совпадают с группами из Build Readme. Если группы из списка не существует – выберите подходящую (и напишите мне личное сообщение, чтобы я обновил эту инструкцию).
      • При установке, вас попросят указать установочные директории. Постарайтесь установить в путь с как можно более коротким имененем, например: C:/cygwin и C:/cygpack. Или вообще c:/cw и c:/cp. Это поможет избежать ошибок с излишне длинными именами файлов, которые не может обработать проводник Windows (NTFS уже иногда может их обрабатывать, а Проводник – еще нет).
      • После изначальной установки, в самом Cygwin нет никакого гуя для управления пакетами. Чтобы установить дополнительные пакеты, нужно заново запустить setup.exe. Эта программа не будет устанавливать Cygwin с нуля, а только докачает нужное. Между перезапусками путь до директорий сохраняется.
      • Выбор зеркала влияет на скорость, но нам нужно скачать очень мало пакетов, поэтому что выбирать — в среднем всё равно. Выбирайте самое первое зеркало в списке.
      • Гуй для установки пакетов немного странный, но вы разберетесь :)
        • Как только вы вписали в поле поиска имя пакета, соответствующий список перерисовывается автоматически – enter жать не нужно.
        • Чтобы установить пакет, нужно много раз прокликать кнопку со статусом (стрелочки замкнутые в уробороса с надписью skip или какой-то еще), чтобы надпись статуса поменялась на версию пакета, которая будет устанавливаться
        • Иногда инсталлятору становится разными способами плохо. Don’t panic.
          Если установка повисла посередине, то самый простой способ всё вернуть назад — удалить C:/Cygwin, или куда вы там его устанавливаете. Лучше не надеяться, что проверяльщик чексумм битых недокачанных пакетов сможет найти поломку, устраните её полным удалением самостоятельно.


    5. Качать make отдельно не нужно.


      В прошлых инструкциях часто предполагалось скачать и прописать свой make.
      По новейшим наблюдениям, делать этого не имеет смысла, того make что установился пакетом в Cygwin — вполне достаточно.

      Более того, на официальном сайте лежит устаревшая версия make, поэтому с ней вы получите ошибку типа:
      The specified make (by MAKE=/cygdrive/c/Program Files (x86)/GnuWin32/bin/make.exe) is not GNU make 4.0 or newer.
      То есть, make вам придется или собирать вручную, или искать уже собранный на сомнительных файлопомойках, как когда-то мы подбирали на них rpm’ки.

      Если собственный make вам действительно нужен, то чтобы его использовать, нужно прописать в configure параметр MAKE=/путь/до/make.exe.
      Да, другие параметры начинаются на --, например --with-freetype, а вот MAKE должен быть именно в таком виде.

    6. DirectX SDK устанавливать не нужно.


      Если оно вам действительно нужно (Java 3D?), вы об этом знаете, и знаете что делать.
      Здесь инструкций не будет.
    7. Собираем FreeType


      Собирать FreeType обязательно, даже если очень не хочется и лично вам не нужно.
      1. Ссылка на загрузку:
        http://ift.tt/1s6oTHF

        Там две группы загрузок: две вверху (Complete package и Sources), и шесть пониже (Binaries… Original source). Элемент Sources есть в обеих группах. Нам нужно скачать зипник элемента Sources из второй группы.

        Замечание:
        Качает сто лет, что делать?
        Ничего не поделаешь, это Сорсфордж. В момент отображения таймера загрузки попробуйте успеть щелкнуть по ссылке try another mirror и выберите что-нибудь во Франции. Французы не жмотятся на скорость.

      2. Создаем директорию src/freetype/2.3.5/freetype-2.3.5/lib
      3. Внутри директории src/freetype/2.3.5/freetype-2.3.5/builds/win32/visual
        лежит солюшен для Студии.
      4. Открываем.
        Если у вас несколько Студий, то от греха подальше лучше открыть в 2013.
        Сборку с 2015 пробовал, она тоже работает.
      5. При открытии солюшена Студия попросит one-way upgrade. Соглашаемся (если отображается несколько элементов в списке – соглашаемся для всех).
      6. После этого Студия может намертво повиснуть, перестав заодним отображаться и в Диспетчере Задач Windows. Тут на помощь приходит Sysinternals Process Explorer:
        http://ift.tt/2i3S6pA
        Нужно найти в дереве devenv.exe, и вначале убить всех его потомков. После этого можно убить и сам devenv.exe (до этого он просто не реагирует на команду умереть).
      7. Идем в Configuration Manager, в выпадашке Platform выбираем New, New platform: x64, Copy settings from: Win32, OK, Close.



      8. Там же, выбираем тип сборки – Release Multithreaded (по умолчанию стоит Debug)
      9. В Solution Explorer, правой кнопкой на проект freetype, properties.
      10. Указываем Output Directory: src/freetype/2.3.5/freetype-2.3.5/lib
        (директория указана относительно корня скачанного FreeType).
        Проверяем, что configuration type выставлен в Static library (.lib)

      11. Закрываем окно freetype Property Pages.
        Собираем проект через Build -> Build solution.
      12. Теперь нужно поменять сборку с lib на dll.

        Повторяем действия:

        В Solution Explorer, правой кнопкой на проект freetype, properties.
        Указываем Output Directory: src/freetype/2.3.5/freetype-2.3.5/lib
        Проверяем, что configuration type выставлен в Dynamic library (.dll)

        Закрываем окно freetype Property Pages.
        Собираем проект через Build -> Build solution.

      13. Открываем директорию src/freetype/2.3.5/freetype-2.3.5/lib в Проводнике и проверяем состав файлов: freetype.dll, freetype.lib, freetype.exp.

        Ключевой факт тут такой: теперь у нас в одной корневой директории (src/freetype/2.3.5/freetype-2.3.5) лежат и инклуды (src/freetype/2.3.5/freetype-2.3.5/include), и библиотеки (src/freetype/2.3.5/freetype-2.3.5/lib).

      14. Готово!
        Теперь у нас есть жалкие 600 килобайт, ради которых мы мучались последние десять минут.
    8. Заливаем исходники JDK из репозитория


      1. Загружаем и устанавливаем Mercurial (TortoiseHg): http://ift.tt/1EPvzxk
      2. Загружаем расширение trees для Mercurial

        Файл: http://ift.tt/2i3Oowk

        Запоминаем, куда скачали (например: C:/opt/trees.py)

        Важно
        Согласно инструкциям отсюда:
        http://ift.tt/2i3HcA4
        Мы должны были бы загружать вот этот файл:
        http://ift.tt/2j1Tho4

        К сожалению, на момент написания статьи, интеграция этого экстеншена с новой версией Mercurial сломана.
        Есть следующий баг, с приложенным патчем:
        http://ift.tt/2j23osQ
        Чтобы вам не патчить trees самостоятельно, я пропатчил его, и выложил здесь:
        http://ift.tt/2i3Oowk
        В будущем, когда этот тикет будет закрыт, стоит использовать основную версию.
        Если вы читаете эту инструкцию, когда тикет уже закрыт – напишите мне, я исправлю этот пункт.

      3. Создаем файл .hgrc в домашнем каталоге пользователя (%USERPROFILE%\.hgrc).

        Так как Windows плохо относится к созданию файлов, начинающихся на точку, проще всего открыть консоль Cygwin и выполнить команду:
        touch /cygdrive/c/Users/olegchir/.hgrc

        Внутри файла пишем:
        [extensions]
        purge =
        trees = C:\opt\trees.py

        Слеши в пути до py-файла – обратные.

      4. Открываем консоль (cmd.exe), переходим в директорию, где хотим хранить исходники (cd C:\git)
      5. Клонируем репозиторий:
        hg tclone http://ift.tt/2i3T4lT 9dev
        Это займет весьма много времени

        Важно
        В будущем ссылка может измениться.
        Смотреть новую ссылку можно здесь: http://ift.tt/1CWsUD0

        Важно
        Постарайтесь установить в путь с как можно более коротким имененем, например: C:/hg. Это поможет избежать ошибок с излишне длинными именами файлов, которые не может обработать проводник Windows (NTFS уже иногда может их обрабатывать, а Проводник – еще нет). Поможет не попасть в глупую ситуацию, когда репозиторий вы уже склонировали, а удалить его — еще не можете.

        Неприятненько
        При возникновении ошибки «abort: stream ended unexpectedly».
        Вначале попробуйте перезапустить hg tclone еще несколько раз.
        Если ошибка продолжает повторятся, то вам предстоит муторная ручная работа.
        Запомните, какой проект не выгружался до конца (например, langtools)
        Перезапустите всё с таким аргументом:
        hg tclone -r 100 http://ift.tt/2i3T4lT 9dev
        Это загрузит только 100 ченжсетов и даст возможность операции tclone завершиться.
        Сразу после этого перейдите в директорию проекта, который не докачался (например, langtools), и выполните hg tpull -u 1000.
        И дальше добавляйте по 1000 ченжсетов:
        hg tpull -u 1000
        hg tpull -u 2000
        hg tpull -u 3000
        Когда ревизии закончатся – нужно перейти в корень (9dev), и выполнить там команду “hg tpull -u” (без указания количества ревизий).
        Если после этого упадёт тот же проект – перейдите в него назад, и с более маленьким шагом докачайте оставшиеся ревизии совсем точно до конца, вернитесь в корень и повторите hg tpull -u без аргументов.
        Если после этого упадёт другой проект – переходим в его директорию, и повторяем пока всё не склонируется до конца.

    9. Собираем JDK


      1. Открываем консоль Cygwin (НЕ cmd.exe), переходим в директорию со склонированными исходниками
      2. Выполняем команду:

        ./configure --enable-debug --with-target-bits=64 --with-boot-jdk=/cygdrive/c/opt/Java/jdk1.8.0_111 --with-freetype=/cygdrive/c/my/opt/java/freetype-2.3.5-1-src/src/freetype/2.3.5/freetype-2.3.5

        пути до файлов должны совпадать с теми, что мы получили в ходе выполнения инструкции:
        --with-boot-jdk указывает на директорию, куда вы загрузили JDK8
        --with-freetype указывает на директорию внутри исходников freetype, где есть поддиректории include и lib, и в lib вы собрали .dll и .lib с 64-битным фритайпом

        пути до файлов обязаны быть не родными, а начинаться с /cygdrive.

      3. Долго ждем, пока сконфигурится. Ошибок быть не должно.

        Единственная ожидаемая ошибка — при использовании Visual Studio Express:
        Cannot locate a valid Visual Studio or Windows SDK installation on disk

        Обычно её можно исправить небольшим грязным хаком.
        Заходим в директорию установки MSVS (обычно это C:/Program Files (x86)/Microsoft Visual Studio 12.0/VC).
        Видим что там нет диерктории amd64, зато есть x86_amd64.
        Копируем её с новым названием: amd64.
        Заходим внутрь amd64, и копируем файл vcvarsx86_amd64.bat с новым именем: vcvars64.bat
        Перезапускаем configure с новым параметром: --with-tools-dir:
        ./configure --enable-debug --with-target-bits=64 --with-boot-jdk=/cygdrive/c/opt/Java/jdk1.8.0_111 --with-freetype=/cygdrive/c/my/opt/java/freetype-2.3.5-1-src/src/freetype/2.3.5/freetype-2.3.5 --with-tools-dir="C:/Program Files (x86)/Microsoft Visual Studio 12.0/VC/bin/amd64"

      4. В результате выполнения configure видим такой текст:

        Configuration summary:
        * Debug level: fastdebug
        * HS debug level: fastdebug
        * JDK variant: normal
        * JVM variants: server
        * OpenJDK target: OS: windows, CPU architecture: x86, address length: 64
        * Version string: 9-internal+0-adhoc.olegchir.openjdk9 (9-internal)

        Tools summary:
        * Environment: cygwin version 2.6.1(0.305/5/3) (root at /cygdrive/c/cygwin)
        * Boot JDK: java version «1.8.0_111» Java(TM) SE Runtime Environment (build 1.8.0_111-b14) Java HotSpot(TM) 64-Bit Server VM (build 25.111-b14, mixed mode) (at /cygdrive/c/opt/Java/jdk1.8.0_111)
        * Toolchain: microsoft (Microsoft Visual Studio 2013)
        * C Compiler: Version 18.00.40629 (at /cygdrive/c/progra~2/micros~2.0/vc/bin/amd64/cl)
        * C++ Compiler: Version 18.00.40629 (at /cygdrive/c/progra~2/micros~2.0/vc/bin/amd64/cl)

        Build performance summary:
        * Cores to use: 8
        * Memory limit: 20447 MB

      5. Выполняем команду: make
      6. Долго ждем, пока соберется.
        В этот момент у компьютера тратится очень много ресурсов – стоит переключиться на использование другого компьютера, или сходить попить чаю.
    10. Проверяем запуск


      Внутри диретктории с исходниками должна появиться директория builds/windows-x86_64-normal-server-fastdebug

      С помощью консоли (cmd.exe) заходим в каталог типа:
      X:\git\openjdk9\build\windows-x86_64-normal-server-fastdebug\jdk\bin

      И выполняем команду: java -version
      Должна быть распечатана версия 9-internal.

    11. Troubleshooting


      In open source no one can hear your scream

      image

    12. PROFIT

    Комментарии (0)

      Let's block ads! (Why?)

      5 языков программирования со светлым (возможно) будущим

      IBM расширила возможности бессерверной платформы OpenWhisk

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

      Сейчас же для работы в такой среде нужен лишь интерфейс загрузки кода с возможностью подключения источников, которые создают события для подключаемого микросервиса. Правда, специфика использования подобной архитектуры предполагает зависимость от работы сторонних BaaS или FaaS систем, которые исполняются в отдельных контейнерах. У компании IBM есть собственный вариант реализации бессерверной архитектуры. Это OpenWhisk, микросервис, который на днях обзавелся более широким набором функций и возможностей, чем ранее.

      На прошлой неделе IBM расширила экосистемы компаний, которые создают и тестируют приложения с использованием Bluemix OpenWhisk. Основные функции самого микросервиса — связывание соответствующих событий и активаторов действий. Это могут быть загрузка изображения или нажатие на мышь или определенную кнопку. После этого следует реакция OpenWhisk c автоматическим последующим подключением различных облачных сервисов. Например, интеллектуального распознавания, IoT, аналитических приложений и прочего. Разработчику работать в таком режиме проще, поскольку он может иметь дело непосредственно с кодом, а не заниматься конфигурированием сервера.

      К числу новых возможностей OpenWisk можно отнести еще и почти мгновенную отладку кода NodeJS, Python и Swift. Добавлена интеграция с рядом инструментариев, а также поддержка ряда языков программирования включая Java, Node v6, Python и Swift v3. Разработчики озаботились и созданием нового пользовательского интерфейса, который упростил разработку и тестирование приложений из браузера.

      «Разработчики работают с „облаками“, желая быть более эффективными… А поскольку OpenWhisk работает с открытыми стандартами, то эта бессерверная платформа может решить ряд проблем, связанных с управлением сервера. Разработчики получают определенную гибкость в выборе использования внешних инструментов и данных, также они могут запустить код из любого места, откуда захочется», заявил Билл Карпович (Bill Karpovich), руководитель подразделения IBM Cloud.

      Bluemix – это новейшее предложение в серии облачных решений IBM. Эта среда позволяет разработчикам и организациям быстро и легко создавать, развертывать и администрировать приложения в облаке. Эта платформа основывается на открытых стандартах и включает около 150 современных технологий и сервисов, включая когнитивные вычисления, блокчейн, Интернет Вещей, облачные сервисы, DevOps и безопасность.

      Комментарии (0)

        Let's block ads! (Why?)

        FuseTools — уникальный инструмент прототипирования и разработки

        О строковом форматировании в современном C++

        Спектроскоп Салтана: лапласианы для фана

        Рождественские дни — время отложить привычные дела и вспомнить забавы — калейдоскопы, мозаики, снежинки… Кто нарисует самую красивую звезду?

        Симметрия радует глаз. Создать красоту нам помогли математика лапласианов, язык Питон и его библиотеки — математический numpy и графический matplotlib.

        Спектры невозможных решеток


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

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

        Уже красиво, только несколько однообразно.

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

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

        Для такой «матрицы расстояний» спектр уже не может быть двумерным. Математике надо каким-то образом подобрать каждой точке такой набор координат (спектр), чтобы удовлетворить нестандартному расстоянию. И спектр начинает звенеть, — количество его компонент в общем случае на единицу меньше количества точек.

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

        Допустим, что наша функция расстояния имеет следующий вид:

        f(R2) = w*Rd + 1/Rd, где w = dist/n^2, Rd = R2^degree.

        Здесь dist и degree — два варьируемых параметра возмущения. Тогда первые 9 вырожденных уровней для представленной выше базовой конфигурации (гексагональной решетки размера 7) при параметрах возмущения dist = -2, degree = 1 имеют вид:

        В левом верхнем углу — исходная конфигурация. Значения параметров подобраны таким образом, чтобы она была почти не искаженной.

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

        Можно взять в качестве исходного набора квадратную решетку. Тогда симметрия будет квадратной:

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

        Добавляем цвет и размер


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

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

        Если варьировать только цвет, то можно поиграть в детскую мозаику:

        Это математика разукрасила базовую конфигурацию точек в разные цвета. А шестиугольные маркеры мы взяли из доступных в matplotlib.

        Паутинки


        Если близкие точки соединить линиями, то мы получим нечто вроде паутины. По научному такая операция называется триангуляцией. Достоинство пакета matplotlib в том, что там такая операция доступна «из коробки». Паутинки красивы:

        Можно удалить часть треугольников на основе масок:

        Мозаики


        Триангуляция становится цветной, если треугольники залить разными цветами:

        Выбор цветовой карты и цветового вектора сильно влияет на восприятие одной и той же конфигурации:

        Использование масок обостряет контуры узоров:

        Количество комбинаций и вариаций практически бесконечно. Игра узоров очень причудлива.

        Контуры


        Возможно, что самыми изысканными являются узоры, полученные с помощью рисования контуров на основе триангуляции. Данные узоры получаются с помощью метода tricontour() библиотеки matplotlib. Даже самые невзрачные и скучные наборы точек приобретают совершенно неожиданные вариации.

        Симметрия может быть любой, например, 5-го порядка:

        На наш взгляд, это магия.

        Спектроскоп


        Все приведенные узоры создавались с помощью программы "Spectroscope" написанной нами на Питоне. Код программы не идеален, но доступен.

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

        Вверху панели управления можно выбрать один из базовых наборов распределений точек (Base). Базовое распределение всегда имеет индекс один, если параметры возмущения равны соответственно -2 (Disturb) и 1 (Degree), поэтому на него можно всегда посмотреть.
        Наиболее мощными являются базовые наборы Hex (гекс) и Square (квадрат), так как в них больше всего точек. Поэтому и разнообразных узоров они дают больше. А вот наборы x-border (границы многоугольников) и особенно Circle (окружность) наоборот — выхолощены и интересны больше для исследовательских целей.

        Для базового набора можно указать его размер (Order) с помощью слайдера (ползунка). Следующее поле (Index) задает номера отображаемых спектров (уровней) из доступных для данного набора. В данной версии можно выводить 1, 4 или 9 узоров одновременно.
        Важный параметр — тип узора (Plot type). Именно он задает способ (режим) отображения наших собственных векторов. Доступные мы перечислили выше (Points, Web, Mosaic, Contour).
        Флажок "Titles" выводит над каждым спектром его числовые параметры, порядковый номер в общем составе уровней и значение собственного числа данного уровня. Это для тех, кому интересна не только графика.
        Ниже мы видим два слайдера для параметров варьирования. При их изменении спектры оживают. Напомним, что правая кнопка мыши на слайдере — сдвигает его к текущему положению, левая — инкрементирует.

        Далее следуют параметры, влияющие на вид спектров — цвет, маркеры и маска. Не во всех режимах отображения они задействованы. Маркеры, например, имеют значение только для «точечного» режима, а маски — наоборот,- для всех, кроме точечного.
        Наиболее важен, пожалуй, цвет (Color). Для его задания необходимо указать цветовую карту (Map). Но играют цветом с помощью вектора (слайдер с флажком Use). Вектор цвета (и размера маркеров тоже) выбирается, как уже отмечалось, из невырожденных уровней.

        В меню программы доступны стандартные функции для сохранения спектров в файлы и экспорта как изображений.

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

        Математические аспекты


        Во время игр со спектрами мы столкнулись с несколькими проблемными вопросами разной степени важности.

        Расчет количества вырожденных спектров

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

        Для гексагональной решетки количество «снежинок» Ns связано с общим количеством точек (узлов) N как:

        Ns = (N-1)/3

        В свою очередь количество точек квадратично зависит от размера решетки a:

        N(a) = 3a(a-1) + 1. Отсюда Ns(a) = a(a-1).

        В квадратной решетке количество вырожденных спектров связано с количеством точек аналогичным образом:

        Ns = N/4 = a^2/4

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

        Идентификация уровней спектра

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

        Фазовые переходы

        Явление бурного изменения узоров происходит в узкой полосе параметра возмущения. Похоже чем-то на фазовый переход. Возможно, что это известное явление. При фазовом переходе меняется как вид спектров, так и их относительное расположение. Мы специально выбрали вид возмущаемой функции таким, чтобы при изменении параметра возмущения Disturb функция меняла знак. Можно видеть, что базовое распределение при изменении параметра с минимального на максимальный переходит с первого индекса на последний. Этот переход осуществляется вроде бы перемещением базового узора по индексам от меньшего к большему. Через какое-то время мы видим измененный базовый узор на последнем индексе. Который затем эволюционирует к исходной базовой конфигурации.
        Однако в больших конфигурациях, похоже, никто никуда не перемещается (ну или мы не можем отследить). Просто в определенный момент возникает зачаток новой базовой конфигурации в нужном месте (на максимальном индексе). Короче, интересно — посмотрите ).
        Если бы у нас был какой-то параметр идентификации собственных уровней — мы бы более точно могли отслеживать перемещение (или смерть и рождение?) спектров. И показывать на картинке всегда заданные спектры независимо от значений их собственных чисел.

        Стабилизация картинки

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

        Делители

        Когда базовой конфигурацией является простая окружность (точки в вершинах правильных многоугольников), то мы сталкиваемся с феноменом делителей целых чисел. В такой конфигурации все точки равноправны. Соответственно все вырожденные уровни (а других тут и нет) также являются координатами вершин многоугольников (лежат на окружности). Но при этом спектры простых многоугольников (число вершин простое число) отличаются от составных. В спектрах простых все уровни — это тоже простые многоугольники с таким же числом вершин. А в спектрах составных уровни состоят из делителей вершин базового многоугольника.
        Например, спектр 30-угольника состоит из 14 вырожденных уровней. Из них четыре 30-угольника, четыре 15-угольника, два 10-угольника, один 6-угольник, два 5-угольника и один 3-угольник. Почему именно такое распределение уровней по делителям — нам не ясно (но мы сильно и не вникали). Возможно, это уже объяснено где-то в теории групп.

        На этом пока все. Удачи в творческом поиске и с Рождеством!

        Комментарии (0)

          Let's block ads! (Why?)

          [recovery mode] Как начать использовать аппаратное шифрование SSD-диска на примере Samsung EVO 850 и программы sedutil

          Поле Галуа на Scala

          Распознавание чеков в Google Docs с помощью ABBYY OCR SDK

          пятница, 6 января 2017 г.

          NoSQL – коротко о главном

          Сергей Туленцев (TextMaster)


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

          Кому будет полезен этот доклад? Это обзорный доклад с претензией на структурированность. Если вы что-то где-то когда-то слышали про NoSQL, то через 40 минут вы будете знать гораздо больше, вы будете легче ориентироваться в терминах и более уверенно выбирать базы данных для своего проекта.

          Поговорим также про типичные примеры применения и как не надо применять NoSQL базы данных.

          Немного истории.

          Впервые термин появляется в 1998 году — так чувак по имени Carlo Strozzi назвал свою реляционную базу данных. Она, однако, не предоставляла SQL-интерфейса для работы с собой, а вместо этого представляла из себя набор bash-скриптов, которые колбасили XML-файлы. Если верить википедии, то последний релиз этой базы данных вышел в 2010 году, и она как-то успешно работала. Я про нее узнал только в процессе подготовки к докладу, и, думаю, это хорошо, что я раньше про нее не узнал.

          В 2009 году другие чуваки из Сан-Франциско организовывали конференцию для обсуждения новых распределенных баз данных, и им нужен был хэш-тег для твиттера, емкий короткий хэш-тег. Кто-то придумал хэш-тег NoSQL, чтобы подчеркнуть, что есть базы данных, в которых есть SQL, есть ACID и всякие крутые штуки, но мы будем говорить про другие базы данных, у которых ничего этого нет. Народу хэш-тег понравился, он вышел из-под контроля и до сих пор гуляет по интернету.

          Термин NoSQL. Есть две трактовки: одна старая, другая новая. Оригинальная — это NoSQL, т.е., вообще, никакого SQL-а нет, а есть какой-то другой механизм, для работы с этой базой данных. И более новая трактовка — это «Not only SQL» — это не только SQL, т.е. может быть SQL, но есть что-то помимо.

          Есть такой сайт http://ift.tt/oVT4bl — это список разных баз данных NoSQL. Содержит описание, тип, ссылку на официальный проект, какие-то краткие важные вещи, которые стоит знать. Можете на досуге залезть почитать, но я про самые популярные сейчас расскажу.

          Наиболее популярная классификация баз данных — это по типам данных.

          Важный тип — это key/value store, или хранилище пар «ключ-значение».

          Это самый густонаселенный тип, и он одновременно самый простой — обладает самым примитивным интерфейсом из всех. И, по идее, минимальный интерфейс для такой базы данных состоит всего из 3-х операций — get, set и delete. Наверное, есть какие-то базы данных, которые удовлетворяют этому интерфейсу, но обычно современные распространенные базы данных предоставляют больше плюшек, например, можно получить много ключей за раз, установить время жизни ключа, ну, соответственно, получить время жизни ключа, какие-нибудь сервисные команды для проверки статуса сервера…

          Яркий представитель этого класса — это Memcashed. И сюда можно отнести с натяжкой Redis. Почему с натяжкой? Потому что у него на самом деле есть своя отдельная категория, в которой есть он один, эта категория называется «серверы структур данных». Он в этой категории находится, потому что у него несколько типов ключей и очень богатый набор команд (150 или больше), с помощью которых можно творить невообразимые вещи, но если эту категорию не учитывать, то так его можно отнести сюда — в key/value. Есть ещё Riak.

          Документ-ориентированная база данных.

          Это сильно усложненный вариант предыдущей категории. Эта добавленная сложность — она дает ещё и бонусы: теперь значения — это не какой-то непрозрачный текстовый блоб, с которым ничего нельзя делать, кроме того, что целиком прочитать или удалить, а теперь можно работать более тонко со значением. Если нам нужна только часть документа, можем ее прочитать или обновить только часть.

          Обычно в базах данных такого типа присутствует богатая структура документа, т.е. дерево. Если грубо представить произвольный JSON, то любой JSON, который можно вообразить себе, можно записать в такую базу данных. И обычно реклама, пресс-релизы говорят — берете любой JSON, кладете в нашу базу данных и потом можно их анализировать. Обычно проблем не возникает только с первым пунктом, собственно с помещением JSON’а в базу данных, а дальше уже начинаются нюансы.

          Типичные представители — MongoDB, CouchDB, ElasticSearch и др.

          Колоночные базы данных.

          Их сильная сторона в способности хранить большое количество данных с большим количеством атрибутов. Если у вас есть пара-тройка миллиардов записей, у каждой из которых по 300 атрибутов — это вам в колоночные базы данных.

          Они немного по-другому хранят данные, нежели, например, реляционные базы данных — реляционки хранят по строкам, т.е. все атрибуты одной строки лежат рядом. Эти делают наоборот, они хранят отдельно колонки.

          Есть файл — в нем хранятся все поля данной колонки из всех 3-х млрд. записей, хранятся все рядом. Соответственно, другая колонка хранится в другом файле. За счет этого они могут применять улучшенное сжатие за счет использования информации о типе данных колонки. Также это может ускорять запросы, если, нам, например, нужны 3 колонки из 300, то нам не обязательно грузить остальные 297.

          Представители — это HBase, Cassandra, Vertica. У Vertica, кстати, SQL интерфейс, но это все равно колоночная БД.

          Графовые базы данных.

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

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

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

          Мультимодельные базы данных.

          Это такие базы данных, в которые одновременно входит две или более категорий из предыдущих.

          Хочешь — пиши документы, хочешь — графы. FoundationDB, например, у нее основной слой — key/value и поверх этого слоя как-то прилажен SQL-слой. Я скачал себе дистрибутив и подписался на рассылку, они мне слали e-mail’ы каждую неделю, но так и не удалось мне поставить и запустить, пощупать как оно работает. И теперь уже не удастся, потому что пару месяцев назад, в марте, этих ребят купила компания Apple и сразу удалила все ссылки на скачку дистрибутива с сайта и теперь, видимо, этот продукт не будет в открытом доступе. Наверное, она работала неплохо, раз их купили.

          Есть ещё две, которые у нас есть возможность пощупать, пока их кто-нибудь тоже не купил.

          Еще есть классификация по способу хранения данных.

          Есть базы данных, которые вообще никак данные не хранят, у них все хранится в памяти. Соответственно, любая перезагрузка процесса влечет за собой потерю данных. Здесь выхода два: либо не хранить там важные данные, которые нельзя восстановить, либо агрессивно применять репликацию. Из неважных данных — это, например, кэш, если у нас кэш куда-то пропадает, то приложение у нас не упадет, оно будет тормозить, пока кэш обратно не поднимется, не разогреется, но ничего смертельного не случится.

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

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

          Этот способ очень хорош, кроме того, что он требует дополнительной памяти. В зависимости от активности, которая происходит на сервере, вам может понадобиться до двукратного запаса памяти. Если у вас база данных 2 Гб, то вам надо держать ещё 2 Гб свободных для сохранения снепшотов.

          Ещё можно настроить, чтобы он писал данные в лог — это другая техника. Т.е., когда ему приходит команда на запись, он ее быстро пишет сразу в лог и продолжает работу, т.е. эти 2 режима — снепшот и лог — они независимы, но можно настроить либо один, либо другой, либо оба вместе. В общем, этот лог тут только дописывается — в этом его плюс, а данные, которые уже попали в лог, они не изменяются и не могут быть поломаны. Поэтому, что обычно люди этот лог кладут на отдельный диск с отдельной головкой, и на этом диске никто, кроме Redis’а, ничего не делает и не трогает головку диска. И эта головка всегда показывает на конец файла. И запись новых операций в конец файла гораздо быстрее, чем если бы это происходило на обычной системе, где происходит другая активность.

          Другие базы данных, например, MongoDB, — у них другая модель, называется in-place updates. У них есть одна копия базы данных, файлов данных, и они прямо “на живую” их изменяют. Это не очень безопасная практика, и если во время изменения, например, отключилось питание, то у вас база данных скарапчена, и сами виноваты. Поэтому несколько версий назад они приделали журналирование — так они называют контрольный лог, и даже сделали его включенным по умолчанию. Поэтому теперь Mongo можно запускать без двух реплик, и будет шанс, что она не попортит ваши данные.

          Говоря про NoSQL нельзя упомянуть про CAP-теорему, это как 2 сапога — пара.

          Теорема была сформулирована в году 2001-м, и некоторые считают, что она утратила актуальность и вообще не стоит про нее говорить, но упомянуть стоит. Она звучит так: распределенная система не может одновременно обладать более чем двумя из следующих трех характеристик — это доступность (availability), согласованность (consistency) и устойчивость к разрывам сети (partition tolerance).

          На самом деле, выбор у нас только из двух вариантов — либо доступность, либо согласованность, потому что partition tolerance у нас везде есть по умолчанию. Мне не известны системы, которые не могли бы пережить разрыв сети, которые при разрыве сети самоуничтожались бы.

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

          В противоположность этому система может быть согласована. Что означает согласованность? Если мы на одном узле записали какие-то данные и спустя некоторое время на другом узле пытаемся прочитать эти данные, если система согласована, мы получим новую версию данных, которую мы записали в другом месте.

          Соответственно, распределенные системы любят относить себя к одному из двух лагерей либо на AP, либо на CP.

          На самом деле есть третий секретный класс — это просто P, но ни один производитель базы данных не любит признаваться, что его система такая, а не из этих двух. То есть, если она просто P — она не обладает ни доступностью, ни согласованностью.

          Соответственно, если система называет себя CP (т.е. consistency и partition tolerance), то при разрыве (если у нас есть кластер, и он разнесен, например, по двум дата-центрам, и связь рвется между дата-центрами) как ведет себя консистентная система? Она, если мы обращаемся на узел, и узел видит, что он не может надежно обеспечить эту запись, что у него нет, например, связи с большинством узлов системы, то он просто откажет приложению в этой записи, и она не удастся. Когда потом связь восстановится, приложение может попробовать снова и у него может получиться.

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

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

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

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

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

          Более умный подход — это использовать типы данных, при использовании которых возникновение конфликтов, если не невозможно, то очень сложно. Например, тип данных — множество. Если у нас есть разорванные кластеры, и мы в одной половине во множество добавляем член А, и в другой половине добавляем B и С. Когда связь восстанавливается, то смерживать эти записи очень легко, мы просто делаем объединение этих множеств, и у нас получается одно результирующее множество (A, B и С).

          Ещё пример — счетчики. Мы можем независимо инкрементировать счетчики, и когда связь восстановится, то мы просто сложим их и получим результирующий счетчик. В базе данных Riak есть специальный термин — CRDT — расшифровывается как бесконфликтные реплицирующиеся типы данных. По аббревиатуре можете загуглить, если интересно.

          Поговорим про использование NoSQL. Когда надо использовать?

          • Если вам нужна высокая масштабируемость.

            Это одна из самых главных, если не самая главная причина использования такого типа баз данных, потому что за счет своей пониженной сложности они легче масштабируются. Если ранее основные тяготы по масштабированию ложились на приложение, например, у нас есть 20 мемкэшей, и приложение собирает их в один хэшринг, чтобы обеспечить безотказность и масштабируемость, то современные базы данных все делают за тебя, в некоторых не надо даже ничего настраивать. Просто запускаешь ноду, она сама находит кластер, вступает в него, скачивает часть данных и начинает отдавать часть данных. Таким образом мы достигаем желанной линейной масштабируемости — это тоже один из святых граалей мира NoSQL.

            Линейная масштабируемость — это когда мы путем увеличения ресурсов кластера получаем пропорциональное увеличение характеристик кластера. Удвоили количество серверов — получили в два раза больше производительность. Если мы линейно масштабируемся — мы очень крутые.

          • Прототипирование — тоже важный пойнт.

            Традиционно реляционные базы данных требуют некоторое количество обслуживания, как до начала, так и во время проекта. Т.е. до начала проекта нам желательно продумать схему базы данных, ее создать, запустить с ней базу данных, а потом, когда проект запущен и работает, могут прийти новые бизнес-требования, или мы обнаружим, что мы как-то ошибались, нам надо добавить колонку… Часто это блокирующая операция. Что это означает? Нам либо нужно класть приложение, т.е. выключать его на минутку, на несколько дней, зависит от сложности ситуации, либо вручную дирижировать процессом обновления схемы. Т.е. накатываем схему на слейв, апгрейдим его до мастера, переключаем на него всех остальных слейвов и на них по очереди тоже накатываем схему. А перед этим надо не забыть выкатить код, который умеет одновременно работать с новой и старой версией базы данных, чтобы ошибки из приложения не летели. Это все делается, но это морока. Зачем делать, когда можно не делать? Поэтому бессхемные базы данных, документ-ориентирование особо, они этим и привлекают, что можно просто начать использовать новую схему данных, и она просто появится в ваших файловых данных. Совсем безболезненно это пройдет в случае, если мы добавляем поля, грубо говоря. Если мы изменяем структуру старых полей, то частенько придется сделать миграцию данных, но все равно это сильно ускоряет и упрощает создание прототипа продукта. Можно за несколько часов на MongoDB накодить минимальный продукт, и когда получим первый раунд финансирования нормально на Postgres писать все это.

          • Высокая доступность — тоже классическая причина.

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

          • Кэширование.

            Здесь нечего говорить, про мемкэш все знаем, применяем. Некоторые товарищи извращаются и ставят Mongo как кэш перед реляционкой, т.е. у нас в реляционной базе данных хранятся данные, все такие нормализованные, а тут приложение делает запрос с 20-тью join’ами, получает результат и кладет его в Mongo, и далее отдает из Mongo. Profit.

          • Родственный случай с кэшированием — это буферизация.

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

          • Очередь заданий — это сестра буферизации.

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

          • Хранилище бинарников.

            Например, нам надо хранить фотки — это на самом деле очень сложная проблема, если у вас фоток очень много, а все социальные сети изобрели свой велосипед для хранения фоток. Но если мы ещё не facebook, а хранить файлы на локальной файловой системе мы не хотим или не можем, потому что их слишком много, то у нас есть несколько выходов. Например, можно воспользоваться сервисом по типу Amazon S3 и просто лить файлы туда. Или можно поднять локальный кластер с Riak’ом или Mongo и хранить файлы там.

            Здесь надо смотреть на ограничение конкретных продуктов. Если я правильно помню, то у Riak’а рекомендации — не класть файлы больше 2-3-х Мб, у Mongo — жесткое ограничение в 16 Мб на документ, но у нее есть специальный механизм для хранения больших файлов, которые бьет файлы по 16 Мб и хранит эти части.

          • Про счетчики мы уже несколько раз говорили.

            Если нам надо что-то быстро считать берем Redis, Riak или Casandra и считаем.

          • Эффективная оценка кардинальности множеств или в простонародьи — «считаем уников».

            Если у нас есть лог просмотров страницы или действий пользователей, как нам узнать, сколько уникальных пользователей здесь участвует? Если эти данные лежат, например, в реляционной базе данных, мы делаем SELECT COUNT(DISTINCT) — и это сработает. Если это не в базе лежит, а просто лог веб-сервера, то мы можем либо какие-то скрипты натравить, либо положить в Hadoop и Hadoop’ом это посчитать.

            У всех этих способов есть один недостаток — производительность просаживается пропорционально увеличению количества данных. Но не стоит отчаиваться на помощь нам придет математика. Есть алгоритм — называется HyperLogLog. Он позволяет радикально уменьшить время и память, требуемые на выполнение этой операции. По ссылке на слайде можете прочитать статью Salvatore (автора Redis’а), который рассказывает про этот алгоритм. Этот алгоритм предполагает, что нам не нужно знать с абсолютной точностью цифру, а мы можем допускать некоторую погрешность, и в этом алгоритме мы можем, используя всего 12 Кб памяти по умолчанию, оценивать кардинальность множеств с миллиардами членов с погрешностью 0,8%. Это константная память — она не будет больше, т.е. если у нас 2 млрд или 7 — она 12 Кб. Размер буфера влияет на точность, чем можно увеличить буфер и уменьшить погрешность. Детали по ссылке (на слайде).

          • Ещё один пример — это система управления контентом.

            Для документных баз данных. Можно взять статью с контентом, с флажками и с настройками и записать ее, и использовать.

          • Полнотекстовый поиск.

            В некоторых реляционных базах данных он встроен и базовые нужды он может удовлетворять, но если вам нужно что-то большее, то нужно брать Sphinx или ElasticSearch.


          Как не надо использовать NoSQL базы данных?

          • Не надо в них хранить реляционные данные.

            Если мы делаем социальную сеть или блог с системой комментариев, или систему с параллельными проектами, у этих систем нет единого фокуса точки зрения на данные. Мы можем смотреть на данные с разных сторон, можем сказать: «дай мне все проекты этого пользователя» или «дай мне всех участников этого проекта, или кто и когда изменял эти страницы», т.е. запросы могут быть совершенно различны, и бизнес-требования могут совершенно внезапно измениться. Хорошо бы, чтобы база данных была достаточно универсальна, чтобы обеспечить эти запросы. Можно постараться и блог или аналог Hacker News написать на Redis’е, но, мне кажется, это очень хрупкая структура, и любое дуновение бизнес-требований порушит все это.

          • В интернетах есть статья, называется «Почему вы никогда не должны использовать MongoDB» — автор Sarah Mei.

            Она описывает идеальнейшее приложение для MongoDB — это база данных фильмов. Там есть сериалы, в сериалах — сезоны, в сезонах — эпизоды, в эпизодах — набор актеров, все это друг в друга вложено, хранится в одном документе, мгновенно достается — красота! И оно так было несколько месяцев, пока на одном из митингов заказчик не попросил её сделать возможность просмотра фильмографии актера, посмотрев все эпизоды, в которых он участвовал. Для реляционных баз данных — это тривиальная задача, но для структуры, которую они имели, это было невыполнимо, потому что актер — не самостоятельный объект, а он вложен в сериалы на 5 уровней вниз — достать его никакой возможности нет.

            Можно переколбасить структуру данных и поднять актера на верхний уровень, а в объекте сезона хранить ссылки, но тогда мы теряем все прелести документной базы данных, потому что мы можем одним запросом поднять все данные, которые нам нужны. Теперь мы поднимаем ID’шники, и по этим ID’шникам надо дополнительно идти искать авторов. Этот один запрос им все сломал, всю радость.

          • Embedding — это когда документ может включать другие документы или массивы документов.

            Здесь у нас гипотетический пример — документ статьи или поста в бложек. У поста есть автор, у автора есть e-mail, у поста есть комментарии, у комментария есть контент и автор. Там ещё можно многое наворотить — есть лайкеры… наворотить можно многое — было бы желание.

            Это все выглядит хорошо на бумаге, но это сломается в тот же момент, когда ваш бложек попадет на крупный СМИ, например, на Хабр (не знаю насколько он крупный СМИ) — ваш бложек сломается сразу же, когда вам под пост нафигачат 10 тыс. комментов за 5 минут.

            У нас в приложении в TextMaster’е была похожая ситуация. У нас есть сущность проекта, у проекта — документ, у документа — атрибуты. Изначально у нас все это хранилось вложено друг в друга, т.е. документы были вложены в проект и все это хранилось. Главной сущностью был проект. Все было хорошо пару недель.

            Через 2 недели после начала эксплуатации у нас все это сломалось, мы вылезли за пределы лимита документов, и у нас появились новые запросы, которые эта структура не удовлетворяла. Нам в срочном порядке нужно было менять структуру данных и поднимать документ, т.е. выдирать его из проекта, поднимать его на верхний уровень и ещё несколько структур нам пришлось выдрать. Т.е. усердствовать с Embedding’ом не надо.

          • В противоположность излишнему Embedding-у — недостаточный Embedding.

            Возьмем 1-ую строчку — это классический пример из туториалов по MongoDB — это теги к какому-нибудь посту. Эта структура, когда значением является массив, Mongo очень хорошо умеет с ним работать, мы можем эффективно искать все посты, например, «дай мне все посты с тегом «ruby»», с тегом ««ruby» и «nosql»» или ««ruby», у которого нет тега «nosql»» — все что хочешь можно делать. Но присутствует избыточность данных, у нас один и тот же текст повторяется много раз, но теги — это вещь, в которой это не страшно. Если мы вышли из мира реляционных баз данных и решили делать все по-старому, то мы сделаем как во 2-ой строчке, мы будем хранить ID’шники тегов, а сами теги будут объектами верхнего уровня, в своей коллекции.

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

          • Неверно выбранный тип данных.

            Это из серии «давай возьмем этот JSON, засериализуем его в строку и положим в строку». Положили — ок. Теперь мы не можем с ним ничего делать, потому что это не прозрачный блоб, и мы можем только целиком его вычитать, целиком перезаписать или целиком удалить.

          • Недостаточно продуманная схема данных.

            На Stack Overflow (есть такой сайт для программистов) не счесть вопросов типа «у меня есть массивы 5-ти уровней вложенности, как мне теперь делать запросы по ней?». Каждый день такие вопросы встречаются. И ладно только запросы, потому что следующий вопрос «А как мне теперь менять эту структуру?». Т.е. люди, не думая, нафигачили каких-то данных и теперь не знают, что с ними делать. То, что по бумагам MongoDB — это бессхемная база данных — не значит, что над схемой думать не надо. Чуть-чуть надо.


          Подытожим.

          Очень полезно знать свою предметную область и пытаться предвидеть будущие запросы, которые могут возникнуть. В примере про сериалы, для заказчика — это было очевидно, что есть ценность в возможности видеть фильмографию актера. Если бы разработчики видели это тоже, то история сложилась бы по-другому. Полезно следить за новостями в мире баз данных. Технологии развиваются очень быстро, и буквально за несколько дней может возникнуть какая-нибудь штука, которая серьезно облегчит вам жизнь. В моем случае — это был тот алгоритм для подсчета уников. И не надо слишком доверять пресс-релизам и рекламе — везде все идеально, надо смотреть ещё на недостатки, здесь возможны варианты, кто-то ищет негативные отзывы по форумам, кто-то читает код, кто-то ждет 3-го service pack’a. Главное выбирать базу данных, исходя не только из достоинств, но и также из недостатков.

          Контакты


          » sergei.tulentsev@gmail.com
          » twitter
          » tech.tulentsev.com
          Этот доклад — расшифровка одного из лучших выступлений на обучающей конференции разработчиков высоконагруженных систем HighLoad++ Junior.

          Также некоторые из этих материалов используются нами в обучающем онлайн-курсе по разработке высоконагруженных систем HighLoad.Guide — это цепочка специально подобранных писем, статей, материалов, видео. Уже сейчас в нашем учебнике более 30 уникальных материалов. Подключайтесь!

          Ну и главная новость — мы начали подготовку весеннего фестиваля "Российские интернет-технологии", в который входит восемь конференций, включая HighLoad++ Junior. Будем ли мы говорить про NoSQL в этом году? Наверняка!

          Комментарии (0)

            Let's block ads! (Why?)