Сохранение данных в БД в 3-звенной архитектуре
От: alesterre Удмуртия  
Дата: 31.01.13 20:01
Оценка:
На сервере в памяти хранятся данные, по запросу клиента изменяются, рассылаются другим клиентам. Данные небольшие и операции относительно простые, поэтому все работает быстро и надежно.

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

Не могу придумать простое решение, по которому сразу можно было бы сказать, что оно работает, и не терзаться сомнениями вида "а что, если?" Как вообще принято делать? Задача выглядит абсолютно стандартной, но что-то ничего толкового не гуглится.
Re: Сохранение данных в БД в 3-звенной архитектуре
От: wildwind Россия  
Дата: 31.01.13 22:43
Оценка: 2 (1) +1
Здравствуйте, alesterre, Вы писали:

A>Как в такой ситуации правильно организовать загрузку и сохранение данных?

Декомпозиция. Читать/сохранять не весь "граф объектов", а по частям. Пока объем изменений в единицу времени остается небольшим, и сохранение будет быстрым.

A>Не могу придумать простое решение, по которому сразу можно было бы сказать, что оно работает, и не терзаться сомнениями вида "а что, если?"

Таких не бывает. У каждого подхода есть свои проблемы и свои "если". Например, при мелкой декомпозиции необходимо поддерживать согласованность частей. Возможно, придется их версионировать.

A>Как вообще принято делать? Задача выглядит абсолютно стандартной

Задача пока никак не выглядит. Мокажи свою модель данных, для начала.
Re: Сохранение данных в БД в 3-звенной архитектуре
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 01.02.13 09:37
Оценка: 2 (1)
Здравствуйте, alesterre, Вы писали:

A>На сервере в памяти хранятся данные, по запросу клиента изменяются, рассылаются другим клиентам. Данные небольшие и операции относительно простые, поэтому все работает быстро и надежно.


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


A>Не могу придумать простое решение, по которому сразу можно было бы сказать, что оно работает, и не терзаться сомнениями вида "а что, если?" Как вообще принято делать? Задача выглядит абсолютно стандартной, но что-то ничего толкового не гуглится.


Если у вас есть Stateful модель на сервере, которая напрямую ложится в базу, то сохранять нужно её из отдельного потока по таймеру, останавливая на это время все обновления.
Это конечно плохо, потому что не масштабируется. True путь это сделать модель отдельно, а базу отдельно. Базу оптимизировать под запись, модель собирать из базы, изменения пишутся и в модель и в базу сразу, ответ пользователю отдается из модели.
Если прикрутить распределенный кеш, то можно еще и несколько серверов поставить.
Re[2]: Сохранение данных в БД в 3-звенной архитектуре
От: alesterre Удмуртия  
Дата: 01.02.13 10:07
Оценка:
Здравствуйте, wildwind, Вы писали:

W>Здравствуйте, alesterre, Вы писали:


A>>Как в такой ситуации правильно организовать загрузку и сохранение данных?

W>Декомпозиция. Читать/сохранять не весь "граф объектов", а по частям. Пока объем изменений в единицу времени остается небольшим, и сохранение будет быстрым.

То есть, все-таки в общем случае стараются сохранять данные сразу же (если нет веских причин этого не делать)?

A>>Не могу придумать простое решение, по которому сразу можно было бы сказать, что оно работает, и не терзаться сомнениями вида "а что, если?"

W>Таких не бывает. У каждого подхода есть свои проблемы и свои "если". Например, при мелкой декомпозиции необходимо поддерживать согласованность частей. Возможно, придется их версионировать.

Эх, жаль. Еще и версионирование. А если пользователи редко открывают одни и те же данные, можно обойтись блокировками? Заблокировать расписание целиком на время сохранения и изменения.

A>>Как вообще принято делать? Задача выглядит абсолютно стандартной

W>Задача пока никак не выглядит. Покажи свою модель данных, для начала.



Из таблицы Schedule загружается одна строчка (одно расписание) и за ней тянется все остальное. В целом расписание загружается из базы за 1-1.5 секунды. К сожалению, полностью декомпозировать изменения затруднительно, потому что, например, иногда бывает нужно сдвинуть несколько десятков точек (таблица SchedulePoint) на указанное количество минут, при этом нужно пересчитать параметры работы (таблица Work), в которую они входят.

У меня есть мысль перенести обработку вовсе на клиента. Пусть ему отправляется все расписание целиком со всеми необходимыми связями, прямо там редактируется и результат время от времени отправляется на сервер, где сохраняется и рассылается другим подписчикам (у кого это расписание открыто). С одной стороны, бизнес-логика переезжает на клиента, что не очень хорошо (но и не слишком плохо). С другой стороны, скорость работы будет максимальной. Бизнес-логику можно (как мне кажется) затолкать внутрь сущностей (self-tracking entities). Самое приятное — вместо кучи разных мелких операций в контракте сервера будет только две — загрузить расписание и сохранить расписание.
Re[2]: Сохранение данных в БД в 3-звенной архитектуре
От: alesterre Удмуртия  
Дата: 01.02.13 10:22
Оценка:
Здравствуйте, gandjustas, Вы писали:


G>Если у вас есть Stateful модель на сервере, которая напрямую ложится в базу, то сохранять нужно её из отдельного потока по таймеру, останавливая на это время все обновления.

G>Это конечно плохо, потому что не масштабируется. True путь это сделать модель отдельно, а базу отдельно. Базу оптимизировать под запись, модель собирать из базы, изменения пишутся и в модель и в базу сразу, ответ пользователю отдается из модели.
G>Если прикрутить распределенный кеш, то можно еще и несколько серверов поставить.

Спасибо, есть о чем подумать. Экспериментальное сохранение по таймеру я уже даже сделал — через полторы секунды после последнего изменения данных — но только для части данных (где тормоза наиболее чувствительны), поэтому были проблемы с простым и надежным блокированием. Подумаю насчет сохранения всей модели целиком. Масштабирование текущему проекту точно не нужно, но мне интересно и в целом тоже, как вообще делают (тем более что масштабирование — один из классических плюсов трехзвенки, и без него ее смысл несколько снижается.).
Re: Сохранение данных в БД в 3-звенной архитектуре
От: . Великобритания  
Дата: 04.02.13 10:30
Оценка:
Здравствуйте, alesterre, Вы писали:

A>На сервере в памяти хранятся данные, по запросу клиента изменяются, рассылаются другим клиентам. Данные небольшие и операции относительно простые, поэтому все работает быстро и надежно.


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

Очевидно должно быть версирование данных и оптимистические блокировки.

A>Как в такой ситуации правильно организовать загрузку и сохранение данных? Загружать один раз и держать в памяти как можно дольше? Сохранять как можно реже, когда данные никто не трогает?

Непонятно. А если сервер упадёт, то все изменения в памяти просто теряются? И такое допусимо?

A>Не могу придумать простое решение, по которому сразу можно было бы сказать, что оно работает, и не терзаться сомнениями вида "а что, если?" Как вообще принято делать? Задача выглядит абсолютно стандартной, но что-то ничего толкового не гуглится.

У меня был опыт с некой подобной системой, тоже некие расписания. Как у нас оно работало: на сервере БД. На клиентах — клоны БД. Клиенты рисуют и отображают информацию только из локальной БД, не делая никаких запросов серверу. Когда юзер делает какое-то действие, оно отсылается серверу, сервер делает изменения, используя данные серверной БД и отсылает изменённые записи всем клиетам, клиенты применяют эти дельты на свои локальные БД.
Получилось довольно неплохо — не требуется мощного/надёжного сервера, система устойчива к тормозным сетям и даже может работать в Read Only режиме при отсутствии сети. Одна была сложность — это права доступа, если клиент не имеет права видеть все данные, то надо как-то хитро определять какому клиенту что можно отправлять, а что нет.

ЗЫЖ Привет, УдГУ!
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[3]: Сохранение данных в БД в 3-звенной архитектуре
От: wildwind Россия  
Дата: 04.02.13 11:53
Оценка:
Здравствуйте, alesterre, Вы писали:

A>Здравствуйте, wildwind, Вы писали:


W>>Здравствуйте, alesterre, Вы писали:


A>>>Как в такой ситуации правильно организовать загрузку и сохранение данных?

W>>Декомпозиция. Читать/сохранять не весь "граф объектов", а по частям. Пока объем изменений в единицу времени остается небольшим, и сохранение будет быстрым.

A>То есть, все-таки в общем случае стараются сохранять данные сразу же (если нет веских причин этого не делать)?


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

A>>>Не могу придумать простое решение, по которому сразу можно было бы сказать, что оно работает, и не терзаться сомнениями вида "а что, если?"

W>>Таких не бывает. У каждого подхода есть свои проблемы и свои "если". Например, при мелкой декомпозиции необходимо поддерживать согласованность частей. Возможно, придется их версионировать.

A>А если пользователи редко открывают одни и те же данные, можно обойтись блокировками? Заблокировать расписание целиком на время сохранения и изменения.


Еще на время чтения. Можно. Получится пессимистическая блокировка.

A>Эх, жаль. Еще и версионирование.

Это не так уж страшно, как может показаться. Версионирование может быть реализовано на уровне СУБД, например.

A>>>Как вообще принято делать? Задача выглядит абсолютно стандартной

W>>Задача пока никак не выглядит. Покажи свою модель данных, для начала.

A>http://i.imgur.com/9yB8IbOs.png


М-да, мало что понятно, да еще с таким написанием.

A>Из таблицы Schedule загружается одна строчка (одно расписание) и за ней тянется все остальное. В целом расписание загружается из базы за 1-1.5 секунды. К сожалению, полностью декомпозировать изменения затруднительно, потому что, например, иногда бывает нужно сдвинуть несколько десятков точек (таблица SchedulePoint) на указанное количество минут, при этом нужно пересчитать параметры работы (таблица Work), в которую они входят.


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

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

A>У меня есть мысль перенести обработку вовсе на клиента. Пусть ему отправляется все расписание целиком со всеми необходимыми связями, прямо там редактируется и результат время от времени отправляется на сервер, где сохраняется и рассылается другим подписчикам (у кого это расписание открыто). С одной стороны, бизнес-логика переезжает на клиента, что не очень хорошо (но и не слишком плохо). С другой стороны, скорость работы будет максимальной. Бизнес-логику можно (как мне кажется) затолкать внутрь сущностей (self-tracking entities). Самое приятное — вместо кучи разных мелких операций в контракте сервера будет только две — загрузить расписание и сохранить расписание.


Тоже вариант.
Re[3]: Сохранение данных в БД в 3-звенной архитектуре
От: hrensgory Россия  
Дата: 04.02.13 12:25
Оценка:
On 01.02.2013 14:07, alesterre wrote:
> Самое приятное — вместо кучи
> разных мелких операций в контракте сервера будет только две — загрузить
> расписание и сохранить расписание.

А если 2 пользователя меняют его "одновременно"? Один из них никогда не
узнает что его изменения затёрты или второй не сможет сохраниться?

--
WBR,
Serge.
Posted via RSDN NNTP Server 2.1 beta
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.