OberonCore

Библиотека  Wiki  Форум  BlackBox  Компоненты  Проекты
Текущее время: Вторник, 16 Апрель, 2024 20:27

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 11 ] 
Автор Сообщение
СообщениеДобавлено: Среда, 13 Июнь, 2007 15:22 
Аватара пользователя

Зарегистрирован: Пятница, 25 Ноябрь, 2005 18:55
Сообщения: 2272
Откуда: Россия, Нижний Новгород
Задача 1.
Есть два компьютера. Один работает, второй - "на подхвате" (standby). Если вдруг первый упадёт (произошла авария), то второй должен тот час же приняться выполнять работу вместо первого. Для этого в его оперативной памяти уже должна быть размещена структура данных из первого компьютера. Вобщем, надо в реальном режиме времени постоянно передавать изменение структуры данных находящейся в оперативной памяти первого компьютера на второй. Естественно, что структура данных слишком большая чтобы можно было передавать её мгновенные копии, нужно передавать именно её изменение.

Задача 2.
То же что и (1), но при аварии имеем полное право "нечаянно" потерять до 10% данных.

Кто-нибудь сталкивался с такими задачами?


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Среда, 13 Июнь, 2007 18:13 
Аватара пользователя

Зарегистрирован: Среда, 29 Март, 2006 12:09
Сообщения: 495
Сергей Губанов писал(а):
Задача 1.
Есть два компьютера. Один работает, второй - "на подхвате" (standby).

Задача 2.
То же что и (1), но при аварии имеем полное право "нечаянно" потерять до 10% данных.

Кто-нибудь сталкивался с такими задачами?


В качестве одного из вариантов решения подобной задачи можно предложить понятие "журнала работы".
Первый компьютер работает, и в процессе работы пишет последовательность обработки [упомянутой большой структуры]. Это и есть журнал. Вводится понятие контрольной точки, которая предназначена для переброски журнала на ведомый компьютер. После передачи первый компьютер продолжает работу, второй выполняет модификацию в порядке поступления журнальной информации. Получается обработка с некоторым запаздыванием. Возможно, потребуется приостановка основного компьютера или какая-то синхронизация, но в целом механизм работоспособный.
Так работает репликация данных на ведомую БД Oracle.

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


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Четверг, 14 Июнь, 2007 13:09 
Аватара пользователя

Зарегистрирован: Пятница, 25 Ноябрь, 2005 18:55
Сообщения: 2272
Откуда: Россия, Нижний Новгород
Похоже, что решение найдено. Ту огромную структуру данных удалось разбить на кластеры, каждый из которых можно (де)сериализовывать по отдельности "обычным Stores", а взаимосвязи между этими кластерами и остальной системой восстанавливать "руками". Но эти кластеры всё же ещё не достаточно мелкие, чтобы отправлять их сериализованное представление по сети после каждой модификации. Для уменьшения трафика мы тут придумали следующее. Буду сериализовать кластер объектов в массив и побайтово сравнивать полученный массив с тем, что был получен при сериализации этого кластера в прошлый раз. Если эти два массива мало отличаются, то пересылатся будет только их разница. Случай удаления кластера обрабатывается отдельно. Расход памяти, правда, увеличивается почти в 2 раза - кроме самой структуры данных хранится ещё и её сериализованная копия.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Пятница, 15 Июнь, 2007 10:25 
Аватара пользователя

Зарегистрирован: Пятница, 25 Ноябрь, 2005 18:55
Сообщения: 2272
Откуда: Россия, Нижний Новгород
Димыч писал(а):
...второй выполняет модификацию в порядке поступления журнальной информации. Получается обработка с некоторым запаздыванием.

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


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Пятница, 15 Июнь, 2007 10:35 
Аватара пользователя

Зарегистрирован: Пятница, 25 Ноябрь, 2005 18:55
Сообщения: 2272
Откуда: Россия, Нижний Новгород
Ещё есть такая идея. Сначала копируем всю структуру (обычным Stores), а затем...

Пусть у каждого объекта будет уникальный идентификатор и пусть будет реестр объектов (идентификатор <--> слабая ссылка).

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

Правда, таким способом не решается вопрос об изменении связей между объектами. Тут надо ещё что-то придумать (наверное, вспомнить методологию Усова (ASU) - установление связей между объектами есть задача их агрегата)...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Суббота, 16 Июнь, 2007 14:51 
Аватара пользователя

Зарегистрирован: Пятница, 25 Ноябрь, 2005 18:55
Сообщения: 2272
Откуда: Россия, Нижний Новгород
А задачка-то, оказывается, имеет точное решение.

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

По сравнению со Stores.Store у реплицируемого объекта есть ещё парочка методов: ReExternalize и ReInternalize. Они предназначены специально для (повторной) модификации ранее экстернализированного/интернализированного объекта. Через них может передаваться не всё состояние объекта, а лишь его модификация, что может быть существенно меньше по объёму.

Есть сервис репликации, у которого есть метод Service.Commit(obj: Object) экстернализирующий или пере-экстернализирующий указанный объект. Когда у объекта-оригинала изменяется состояние, то он сообщает об этом сервису репликации вызывая: service.Commit(this). Если (пере)экстернализируемый объект ссылается на другие объекты и они ещё не были ни разу экстернализированы, то они экстернализируются. Пере-экстернализация выполняется только по явной команде.

У каждого реплицируемого объекта есть скрытое поле - GUID, благодаря ему восстанавливаются все взаимные ссылки при десериализации.

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

Концептуальный интерфейс:
Код:
DEFINITION Replication;

  TYPE
    Object = POINTER TO ABSTRACT RECORD
      (obj: Object) Externalize- (VAR wr: Writer), NEW, EXTENSIBLE;
      (obj: Object) Internalize- (VAR rd: Reader), NEW, EXTENSIBLE;
      (obj: Object) ReExternalize- (VAR wr: Writer), NEW, EXTENSIBLE;
      (obj: Object) ReInternalize- (VAR rd: Reader), NEW, EXTENSIBLE
    END;

    Reader = LIMITED RECORD
      (VAR rd: Reader) ReadByte (OUT b: BYTE), NEW;
      (VAR rd: Reader) ReadBytes (OUT buffer: ARRAY OF BYTE; offset, count: INTEGER), NEW;
      ...
      (VAR rd: Reader) ReadObject (OUT obj: Object), NEW
    END;

    Writer = LIMITED RECORD
      (VAR wr: Writer) WriteByte (b: BYTE), NEW;
      (VAR wr: Writer) WriteBytes (IN buffer: ARRAY OF BYTE; offset, count: INTEGER), NEW;
      ...
      (VAR wr: Writer) WriteObject (obj: Object), NEW
    END;

    Service = POINTER TO ABSTRACT RECORD
      (c: Channel) Commit (obj: Object), NEW, ABSTRACT;
    END;

  PROCEDURE NewService (listenerEndPoint: ARRAY OF CHAR): Service;

END Replication.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Суббота, 16 Июнь, 2007 15:32 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9459
Откуда: Россия, Орёл
Сергей, а реализация будет на КП?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Воскресенье, 17 Июнь, 2007 18:17 
Аватара пользователя

Зарегистрирован: Пятница, 25 Ноябрь, 2005 18:55
Сообщения: 2272
Откуда: Россия, Нижний Новгород
Илья Ермаков писал(а):
Сергей, а реализация будет на КП?

Ну, мне же это на работе надо, а мы там не на КП пишем...

Я уже где-то на этом форуме писал, что если бы была "железобетонная" серверная версия Блэкбокса под Linux, которая бы не уступала как минимум реализации тамошнего .Net - Mono, то кто знает, может быть была бы и на КП.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Понедельник, 18 Июнь, 2007 17:44 
Аватара пользователя

Зарегистрирован: Среда, 29 Март, 2006 12:09
Сообщения: 495
Сергей Губанов писал(а):
Ещё есть такая идея. Сначала копируем всю структуру (обычным Stores), а затем...

Пусть у каждого объекта будет уникальный идентификатор и пусть будет реестр объектов (идентификатор <--> слабая ссылка).

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


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

п.3 и имелся ввиду под "журналом".
Вопрос передачи журнала на ведомый компьютер - предмет отдельного обсуждения, возможных вариантов масса - сокеты, RPC, http и т.д.
По варианту №3 работает (насколько я знаю) удаленный рабочий стол в Windows (в добавление к приведенному выше Ораклу). Там производится запись команд GDI наподобие WMF и передаются записанные команды, которые затем воспроизводятся на удаленном столе.

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

PS. Можно какую-то ссылочку на более подробное описание решения с сериализацией?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Вторник, 19 Июнь, 2007 09:58 
Аватара пользователя

Зарегистрирован: Пятница, 25 Ноябрь, 2005 18:55
Сообщения: 2272
Откуда: Россия, Нижний Новгород
Там не просто структура данных, а взаимосвязанные объекты. Данные в них инкапсулированы и наперёд не известно что там внутри объектов и как изменяется. С этой точки зрения каждый объект атомарен.

Ссылочку на сериализацию можно - смотрите в Блэкбоксе модуль Stores.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Вторник, 19 Июнь, 2007 17:29 
Аватара пользователя

Зарегистрирован: Пятница, 25 Ноябрь, 2005 18:55
Сообщения: 2272
Откуда: Россия, Нижний Новгород
Кстати, методы ReExternalize (VAR wr: Writer) и ReInternalize (VAR rd: Reader) логичнее обозвать как BeginReplication (VAR wr: Writer) и EndReplication (VAR rd: Reader). Метод BeginReplication (VAR wr: Writer) вызывается системой у объекта-оригинала на одном компьютере, а метод EndReplication (VAR rd: Reader) вызывается системой у объекта-копии на другом компьютере. При этом соответствующие Writer и Reader относятся к одному и тому же Carrier - переданному по сети бинарному сообщению.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 11 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 7


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Вся информация, размещаемая участниками на конференции (тексты сообщений, вложения и пр.) © 2005-2024, участники конференции «OberonCore», если специально не оговорено иное.
Администрация не несет ответственности за мнения, стиль и достоверность высказываний участников, равно как и за безопасность материалов, предоставляемых участниками во вложениях.
Без разрешения участников и ссылки на конференцию «OberonCore» любое воспроизведение и/или копирование высказываний полностью и/или по частям запрещено.
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB