Задача стоит следующая: есть удалённый хост для сбора данных с датчиков. Он сделан максимально компактным и малопотребляющим на базе минироутера TP-Link TL-MR3020 с 3G модемом и флешкой. Датчики опрашиваются непрерывно с интервалом в 5 минут. Требуется данные с датчиков складывать в базу MySQL на отдельном сервере.
Требования:
1) При рабочем канале 3G модема данные должны передаваться с задержкой не более интервала опроса датчиков 5 минут.
2) При нерабочем канале данные должны накапливаться локально и сбрасываться в БД как только канал восстановится.
3) В случае сбоя на минироутере (сбой питания, зависание) надо обеспечить сохранность непереданных данных на флешке.
4) Хранить полную копию БД на минироутере не следует.Собственно, а как такое делается грамотно? Складывать данные с каждого опроса в отдельный файлик и крутить в скрипте цикл "есть файл? - передали INSERT серверу; удачно? - прибили файл" как-то не элегантно. Скажем, канал пролежал неделю и поднялся, что теперь долбить сервер две тысячи раз отдельными запросами? Можно ли запустить локально второй сервер MySQL, оперативно складывать данные на него и делать каким-то образом накопительные апдейты таблицы БД на главном сервере силами самого MySQL? Это не репликация получается, а вот как, я не соображу, чтобы нагуглить. Есть красивые решения на этот счёт?
Как вариант:Включить бинарные логи и с помощью скрипта парсить их и передавать на удалённый сервер нужные вам команды. Т.е. скриптом можно даже вырезать команды, которые не нужно передавать (DELETE в вашем случае, как я понял). Алгоритм примерно такой:
1) SHOW MASTER STATUS -- посмотреть номер последнего файла бинарного лога;
2) FLUSH LOGS -- сделать ротацию бинарных логов;
3) /usr/bin/mysqlbinlog -- получить команды в текстовом виде из бинарных логов (имя последнего файла для обработки вы получили на первом шаге, а имя первого - читайте из файла, в который сохранили номер на 5-ом шаге прошлого запуска);
4) парсинг файла с результатом команды на предыдущем шаге, передача данных на удалённый сервер и загрузка их в БД;
5) если 4-ый шаг отработал корректно, то увеличиваем на один число, полученное на первом шаге, и сохраняем его в файл для 3-го шага следующего запуска.
> Как вариант:
> Включить бинарные логи и с помощью скрипта парсить их и передавать на
> удалённый сервер нужные вам команды.Спасибо за вариант! Но тут получается та же история, что и с хранением необработанных запросов к удалённому серверу в отдельных файлах. Т.е. надо последовательно разобрать лог на запросы и все их повторить. Плюс к файлам, надо ещё отслеживать, что мы передавали, а что нет и, собственно, функции локального MySQL тут ничем от папки с файлами не отличаются, т.е. избыточность решения высока.
Я думал, что вдруг есть функция в MySQL, которая позволяет двум серверам самостоятельно решать такую задачу в автомате по принципу "подключились к коллеге, ага вот у него есть запись с таким ключом, а у меня нет - перемещаем её к себе". Но если такого нет, видимо проще всего и надёжней вариант с хранением каждого запроса на передачу удалённому серверу в отдельном файле.
> Собственно, а как такое делается грамотно? Складывать данные с каждого опроса в
> отдельный файлик и крутить в скрипте цикл "есть файл? - передали
> INSERT серверу; удачно? - прибили файл" как-то не элегантно. Скажем, канал
> пролежал неделю и поднялся, что теперь долбить сервер две тысячи раз
> отдельными запросами?less than nothing.
Перемудришь самого себя паря :) 2000 запросов твой сервак прожует за 10 сек.
> Задача стоит следующая: есть удалённый хост для сбора данных с датчиков. Он
> сделан максимально компактным и малопотребляющим на базе минироутера TP-Link TL-MR3020
> с 3G модемом и флешкой. Датчики опрашиваются непрерывно с интервалом в
> 5 минут. Требуется данные с датчиков складывать в базу MySQL наЗадача на самом деле дикой сложности. Возьми какую-нибудь Promela и промоделируй систему во всех переходных состояниях.
Во-первых net.ipv4.tcp_retries2 по умолчанию сильно превышает 5 минут. Спец. конфигурация возможна, но это геморрой - следить, чтобы никакая блядь не крутанула настройки после какого-нибудь апгрейда.
Во-вторых, если постоянно ожидать сбоя питания, то по каждой записи в файл нужно бы сбросить дисковые буфера и закрыть файл. То есть перезаписать минимум пару блоков. Так у тебя 10тыс. жизней и кончатся (100тыс. для старых SLC). Self-healing flash в продаже пока нет, могут вообще передумать выпускать.
Протокол переделать на UDP. Датчик опросил - плюнул наружу пакет, подождал X сек. ответа от сервера. Ответа нет - ещё неск. раз плюнул. Ответа всё нет или интерфейс лежит - пакет в очередь в память. Набралось X килобайт - скинули в файл.Раутеру на питалово подключить конденсатор на полфарады-фараду. Напаять цепь опознавания пропажи питания, завести хотя бы и на кнопку WPS. Кнопка нажата - демон сбрасывает буфера на флешку и готовится умирать. Учти, что питание может вернуться. Ещё учти, что может дребезжать - то потухнет, то погаснет.
Опознавание ситуации "возврат после залёта", переброска файла с флешки и стирание файла - это уже просто.
А вообще грамотно - это не делать индустриальные системы из говна и палок.