среда, 27 февраля 2019 г.

Redis-кластер в докерах

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

docker run --name xredis -d redis:alpine
docker run --name yredis -d redis:alpine
docker run --name zredis -d redis:alpine

IP_X=$(docker inspect --format '{{.NetworkSettings.IPAddress}}' xredis)

docker exec -it yredis redis-cli slaveof $IP_X 6379
docker exec -it zredis redis-cli slaveof $IP_X 6379

Грохнуть кластер (удалить все контейнеры) можно с помощью другого скрипта:

docker rm -f xredis
docker rm -f yredis
docker rm -f zredis


Singularity - Docker для суперкомпьютеров

На многопроцессорных машинах, где распределением нагрузки по узлам занимается планировщик, используют специальные контейнерные решения. Одним из них является Singularity. В статье Singularity : a "Docker" for HPC environments  перечисляются преимущества этой платформой - безопасность, переносимость и т.д. В комментариях один пользователь перечислил другие средства для работы с контейнерами на суперкомпьютерах (UNIVA и что-то Майкрософтовское). А быстрый старт по Singularity можно почитать здесь . 

вторник, 26 февраля 2019 г.

Сети контейнеров Docker

Оказалось, что флаг --link - это устаревший способ соединения контейнеров. Теперь это можно делать с помощью сети.

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

Посмотреть состояние сети (в т.ч. информацию по каждому контейнеру):
docker network inspect bridge

Выдрать ip-адрес контейнера yredis и сохранить в переменную IP_Y:
IP_Y=$(docker inspect --format '{{.NetworkSettings.IPAddress}}' yredis)

Изнутри контейнера xredis запустить консоль redis-cli, которую присоединить к экземпляру Redis, который крутится в контейнере yredis:
docker exec -it xredis redis-cli -h $IP_Y

Очевидно, про --link можно забыть. Если контейнеров хотя бы 5 штук - уже вручную их не увяжешь. А к bridge контейнеры присоединяются вручную.

понедельник, 25 февраля 2019 г.

ПО в докерах

Буду кидать сюда ссылки на полезные материалы по работе с различным ПО в контейнерах

Hadoop
Some tips to run a multi-node Hadoop in Docker

Zookeeper
страница образа на DockerHub

MySQL

Basic Steps for MySQL Server Deployment with Docker
More Topics on Deploying MySQL Server with Docker

воскресенье, 24 февраля 2019 г.

Соединение контейнеров Docker


Соединить два контейнера оказалось не так и сложно. Запустим первый контейнер под именем mredis: 
docker run --name mredis -d redis:alpine

Запустим другой под именем yredis. Присоединим его к контейнеру mredis, который будет хостом под тем же именем (поэтому mredis:mredis после link): 
docker run -d --name yredis --link=mredis:mredis redis:alpine

Теперь изнутри yredis я могу запустить консоль Redis, которую подключу к хосту mredis:
docker exec -it yredis redis-cli -h mredis

А как соединить несколько контейнеров? На stackoverflow пишут, что вот так:
docker run -d --link node1:node1 --link node2:node2 --link node3:node3 -p hostport:containerport your-image

четверг, 21 февраля 2019 г.

Docker: первые шаги

Занялся я тут всеми этими докерами-шмокерами. Ну, в целом, не так уж все и сложно. Хотим, допустим, с Redis поиграться. Пишем
docker run --name mredis -p 6379:6379 -d redis:alpine


Поясню: run - запустить контейнер из образа redis:alpine (т.е. редис на основе Alpine - всего 5 Мб; если на локальной машине такого образа нет - он будет стянут с DockerHub), имя контейнера будет mredis, открываем порт контейнера 6379, который прикрепим к порту нашего сервера 6379). Флаг -d говорит, что контейнер запустится в фоновом режиме.

Теперь нужно поработать с Redis, т.е. нужно запустить консоль redis-cli. Делается это изнутри запущенного контейнера:
docker exec -it mredis redis-cli


Ну, и еще пару мелочей. Остановить контейнер:
docker stop mredis
удалить контейнер:
docker rm mredis
посмотреть запущенные контейнеры
docker ps
посмотреть все (в т.ч. остановленные) контейнеры
docker ps -a


Очень интересно, как связать два контейнера. Скажем, в одном крутится СУБД, в другом - клиент. Это рассказано в статье How to Connect Docker Containers . Разберусь с этим потом.

вторник, 19 февраля 2019 г.

На смену Hadoop идет Kubernetes

Столько разговору было про эти хадупы-шмадупы, и вот... В статье Is Hadoop Dead? How Kubernetes and Cloud-Native Could Displace Hadoop утверждается, что Хадуп потихоньку сдувается. Пик популярности пройден в 2015м.

Автор отмечает недостатки Хадупа:
  • сложен в освоении
  • много записей на диск
  • обработка данных пакетная - поэтому неприменим для аналитики в реальном времени
Короче, нужно что-то еще. Apache Spark - скажет большинство. Но вот, оказывается, есть еще одна восходящая звезда - Kubernetes, менеджер контейнеров.

Чуть подробнее рассказано в статье Modern Big Data Pipelines over Kubernetes . Вкратце, там говорится, что людям мало стандартной инфраструктуры Hadoop ((Map/Reduce, YARN и HDFS) . Нужно, чтоб кластер умел работать с такими вещами как  Kafka, Spark и TensorFlow,  и такими СУБД как Cassandra, Elasticsearch и облачными хранилищами. Почему это невозможно с Хадупом - я пока не разобрался.

В статье также упоминаются serverless frameworks (Kubeless и OpenFaaS). Они легко разворачиваются без докеров, yaml и т.д. Т.е. уже и сервера не нужны?)) 

А еще говорится о Nuclio. Это платформа (тоже serverless) , которая использует Kubernetes вместо YARN, что позволяет работать с такими фреймворками как Spark ML, Presto, TensorFlow & Python. 

Интересно, конечно, но где гарантии, что все эти чудеса инженерии не окажутся очередными спиннерами?

понедельник, 18 февраля 2019 г.

Структура проекта и makefile

Понадобилось сделать хорошую прозрачную структуру проекта, чтоб не путаться. Нашел статью A Simple C++ Project Structure, где расписана типовая структура проекта. Исходные тексты держим в src, объектные файлы в build, тестовые в test, заголовочные файлы в include и т.д. Не очень понятно, это и есть full GNU C++ standard project? Мне и такой структуры хватит.  

Пришлось учится писать мейкфайлы под многопапочную структуру. А я в языке make не силен. Нашел, наконец, простое описание автоматических переменных (здесь). В выражении
                     all: library.cpp main.cpp
переменная $@ равна all, $< - это library.cpp, а $^ - это library.cpp main.cpp.

Сам makefile не выкладываю, он далек от идеала. Но принцип такой - компилируем исходники из src и tst в объектники, их отправляем в build. Затем все объектники собираем в бинарник, который отправляем в bin.

четверг, 14 февраля 2019 г.

Конструктор копирования в C++

Конструктор копирования в классе MyClass будет выглядеть так:
           MyClass(const MyClass &arg)
Почему const? Потому что при копировании оригинал не должен меняться. Почему параметр по ссылке передается? А потому что, если по значению, то будет происходить копирование аргумента. Т.е. в функции, которая должна копировать происходит вызов функции копирования... Бесконечная рекурсия.

Конструктор копирования вызывается
  1. При инициализации объекта
    MyClass a;
    MyClass b = a; //инициализация объекта b объектом a
  2. При передачи объекта в функцию по значению (создается копия аргумента)
  3. При возвращении по значению (создается временный объект)
(Про всё это хорошо написано в памятке C++ Notes: OOP: Copy Constructors)

Таким образом, в следующем коде конструктор копирования будет вызываться дважды
MyClass make_obj()
{
            MyClass c;
            return c;
}

int main()
{
           MyClass a = make_obj()
 }

Конструктор копирования вызывается при создании временного объекта, возвращаемого из фунции и при инициализации объекта а. 

Но. Откомпилировав программу с помощью g++ и запустив, мы увидим, что конструктор копирования ни разу не вызывается! Чтоб в этом убедиться - вставим в конструктор отладочный вывод. 

Как же так? Компилятор оптимизирует? Но флаг -O0 не помог, всё по-прежнему.

Отгадка нашлась здесь.
man GCC-4.4.7:
-fno-elide-constructors
The C++ standard allows an implementation to omit creating a temporary which is only
used to initialize another object of the same type.
Т.е. все дело действительно в оптимизации, просто отключать ее нужно специальным флагом


вторник, 12 февраля 2019 г.

База данных COD

COD (Crystallography Open DB) оказалась здоровенной - 54 Гб. Команда du -sh COD шуршала в районе 2 мин, чтоб выдать мне этот результат.

Полезные ссылки:
- как скачать COD;
- описание файлового формата  mmCIF (основной формат в COD);
- отличная презентация Big­Data Analytics in Materials Science на тему анализа подобных БД - постановки задач, ссылки на работы, список открытых химических и материаловедческих БД;
- полное описание формата файла cif ;
- примерчик изготовления простейшего cif-файла;
- подробное руководство A guide to CIF for authors.

Может быть, пригодится статья Crystal Structure of Graphite, Graphene and Silicon

понедельник, 11 февраля 2019 г.

О потоках данных

Пытаюсь вникнуть в тему, пока какие-то крупицы собираю по разным статьям. Вот, скажем, текст "Как построить IIoT архитектуру своими руками". На предприятии много датчиков, они передают информацию на шлюз (в его роли выступает Raspberry Pi). На шлюзе крутится брокер Mosquitto, который дальше будет гнать данные по MQTT. Кроме того, в системе участвует Apache NiFi - система управления потоками.

Overcomittment

Столкнулся с этим термином применительно к виртуальным машинам. Стал гуглить, нашел хорошее определение здесь


Вольный перевод первого абзаца:
Memory overcommit (или overcommitment) - это возможность гипервизора выделить виртуальным машинам (суммарно) больше памяти, чем имеется физически. Например, платформа виртуализации VMware ESX позволяет запустить 4 гостевые машины с 1 гигабайтом на каждую на сервере с 2 Гб оперативной памяти.



среда, 6 февраля 2019 г.

Большие научные базы данных

Где взять большие данные, вопрошают те, кто хочет заняться модным направлением Big Data. Банки и сотовые операторы не отдадут ведь накопленную информацию, это ж понятно. Эххх :(
Но почему б не заняться аналитикой научных данных? Ученые - люди добрые, массу всего интересного в открытый доступ выкладывают. 

Вот, например, Protein Data Bank (PDB). Содержит массу информации о структуре всяких белков. Насколько я знаю, там в районе 40 ГБ данных. Поиск по PDB можно делать на этой страничке.  Там в основном файлы в формате .cif. Информация о работе с этим форматом есть на mmcif.wwpdb.org

А еще есть Crystallography open database. Располагается здесь. Думаю, там не меньше данных собрано.


Pig и Hive

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

Выделю основное. В Hive запросы пишутся на HQL - аналоге SQL. Внутри проебразуются в MapReduce, за счет чего выборки должны шустро работать на кластере. Однако сложные запросы на языке HQL превращаются в нечто трудночитаемое, поэтому в этом случае есть смысл переходить на Pig.

В Pig более богатый язык запросов PigLatin (который, однако, имеет кое-что общее с SQL). Кроме того, предусмотрено несколько структур данных.

понедельник, 4 февраля 2019 г.

Про boid

Boid - это алгоритм симуляции стайного поведения (flocking behavior).

Каждый бойдик в стае придерживается трех основных принципов: 

  1. Стая должна оставаться единым целым, для этого каждый участник движется в направлении к центру относительно ближайших соседей;
  2. Бойды стараются не сталкиваться - движутся от соседа, если расстояние стало слишком маленьким;
  3. Бойды стараются сделать свою скорость близкой к скоростям соседей.
Подробнее можно прочитать в разделе Flocking замечательной книги AI for Game Developers (полностью выложена в онлайн). 

Компилируем .cpp как С-программу

Вот тут есть хорошие примеры. Компилируем cpp файл как программу на С:
         gcc -x c your-file-name.cpp
Первый файл компилируем как C программу, второй - как программу на С++ (отменяем действие -x c с помощью -x none):
         gcc -x c your-filename.cpp -x none other-file-name.cpp

воскресенье, 3 февраля 2019 г.

Leader lease и миграция схемы

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

Читаю, значит, интересный пост на eax.me : Колхозная реализация выбора лидера на Go и Consul . Там рассказана интересная идея по поводу организации лидерства среди реплик. Делается это с помощью записи в некое хранилище ключ-значение (здесь выбран Consul). Важным моментом является наличие compare and swap - чтоб при чтении одной и той же записи разными репликами не возникало бы состояния гонки.

Так вот, тут упоминается понятие leader lease. А не консенсус или выбор лидера. Полез искать этот самый лиз. Нашел в документации по CockroachDB. Здесь есть понятие leaseholder - реплика, которая координирует запросы на чтение и записи (обычно совпадает с репликой-лидером, выбранной Raft). Почему-то уменьшает количество вызовов RPC - в этом пока не разобрался. Есть статья про Аврору, где говорится, что в Cockroach запрос на чтение или запись направляется той реплике, у которой в данный момент временное лидерство (lease). Упоминание про lease встречается и в описании консенсуса в Consul.

Как пример ситуации, когда необходим этот самый лиз, в посте на eax упоминалась миграция схемы БД. Это что еще?! Неплохо объясняется в Вики.  Вкратце - это процесс изменения схемы БД. Она может меняться параллельно с разработкой ПО. И если развитие ПО контролируется системой контроля версий, то со схемой так не получится. Она поменяется, а наша программа не сможет найти в ней нужные столбцы. Конкретные советы, как делать миграции даются в статье "Миграция схемы данных без головной боли: идемпотентность и конвергентность для DDL-скриптов". Хм, идемпотентность и конвергентность? Сразу навевает мысли о CRDT, не так ли?

пятница, 1 февраля 2019 г.

Новое о gdb

Вот интересно - как посмотреть значение константы, которая задана с помощью #define? Если просто сделать print CONST - отладчик скажет, что он никакого CONST не знает. Как быть? При компиляции gcc задать флаг не -g, а -g3. Тогда задефайненные константы можно будет распечатать.

Можно ли вызывать функции отлаживаемой программы в gdb? Можно, используя call. Это хорошо для отладочной печати - у нас сложная структура, пишем функцию распечатки, в отладчике вызываем эту функцию. Опять-таки, использовать задефайненные константы в качестве аргументов можно только если программа откомпилирована с -g3.

И совсем интересное. Есть переменная i - обычный индекс для цикла for. Пытаюсь что-нибудь про неё узнать: info address i. Мне пишут Symbol "i" is a variable with complex or multiple locations . Это как? Несколько мест расположений? У меня правда две i - локальная в main и локальная в show_arr. Может, это имеется ввиду.