| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Java EE (J2EE) и Spring > Целостность информации |
| Автор: Zamuta 18.6.2007, 04:05 |
| Здрасьте. У меня опять вопрос по архитектуре, т.к. в книжках конечно всё красиво пишут, но про реальную работу приложений лучше поинтересоваться у Вас. Суть такая. Некий класс записывает в бд информацию в результате проделанных юзером манипуляций. Причём и имена таблиц и сама информация разные в зависимости от действий юзера. Сначала данные кладутся в сессион мап, а затем по этим данным делаются записи в бд. В конечном итоге на одного юзера приходится около 6-8 инсертов, селектов за раз, т.е. единовременно. Коннект с бд через пул. В конце, когда юзер сделал все свои манипуляции и хочет сделать сохранение он таким образом запускает цепочку методов, которые тянут инфу из сессии и в результате происходит запись. А что если в один момент времени данные попытаются сохранить 10 юзеров. Мы ведь не исключаем такой ситуации. Целостность информации в бд можно обеспечить транзакциями, но т.к. все они будут тянуть одну и ту же цепочку методов, то не возникнет ли здесь неожиданных моментов? В зависимости от загрузки бд одни данные уйдут сразу, другие будут ждать окончания транзакции, а тут ещё кто-то пытается сделать сохранение. Я к тому что вызов той самой цепочки методов для каждого юзера происходит последовательно или они все будут сваливаться в кучу? Я хочу обеспечить именно последовательность выполнения операций. Что здесь больше подойдёт singleton или делать методы synchronized ? |
| Автор: Zamuta 18.6.2007, 06:58 | ||
nornad,
Ты имеешь в виду java.util.Stack ? А конкретно для веба своего решения ситуации нет? Скорее всего я не первый с этим сталкиваюсь.... |
| Автор: MisterCleric 18.6.2007, 09:56 |
| привет. nornad правильно, говорит: надо организовать очередь. Посмотри в сторону шаблона Command. И тебе нужно еще учесть момент, что юзер делал-делал что-то, а тут ему захотелось все отменить ..., или не все .... |
| Автор: nornad 18.6.2007, 10:15 |
Если говорить про конкретный контейнер, то использовать нужно не стек (Stack), а очередь (Queue). Насчёт готовых решений для вэба (о котором, кстати, изначально ничего не говорилось) я не в курсе - с вэбом почти не работаю. |
| Автор: Stampede 18.6.2007, 23:00 |
| Zamuta, недостаточно инфы. По тому скудному описанию, что ты привел, я бы посоветовал изолировать транзакции на границе бизнес-метода. Например, объявить его как synchronized (предполагая, что это класс-синглтон), или через какой-то статический объект, используемый в качестве замка, или через один из примитивов синхронизации. В этом случае ты без лишнего гемора добъешься того, что все запросы на выполнение данного метода будут автоматически выстраиваться в очередь. Плюс - стопудовая гарантия целостности транзакций. Минус - возможные проблемы с масштабируемостью, а также недоиспользование аппаратных мощностей. Чтобы предложить что-то более конкретное, нужна более подробная инфа. В частности, интересует следующее:
Да, а насчет очереди Queue - это тебя тут маленько ввели в заблуждение. Вряд ли она поможет в твоем случае. Решения такого рода помогают организовать асинхронное выполнение операций, но тебе, как я понял, это не требуется. |
| Автор: Zamuta 19.6.2007, 01:31 | ||||||||||||
Stampede,
Вот именно это мне и нужно, но вопрос в том правильно ли всё будет работать без этих мер? С одним юзером всё понятно, но какой же интернет ресурс имеет только одного пользователя ?
Транзакции конечно же необходимы, за одну транзакцию происходит выбор и запись по 5-8 таблицам, но это уже проблемы бд (mysql). О том сколько времени занимает транзакция можно судить лишь о том что используются prepared statement и запросы по своей структуре не сложные, селекты и инсерты осложнены только where username_id = '', т.е. везде отталкиваюсь от порядкового номера юзера в бд.
Предполагается создание достаточно посещаемого ресурса, думаю пиковая нагрузка на первое время около 20-30 вызовов/сек того самого метода о котором мы говорим, обращений к бд само собой больше, но уже только селекты
Нет, только один метод. Но в моём понимании это будет в случае с synchronized синглтон, потому и такой вопрос. В книге С.Стелтинг О.Маасен Применение шаблонов java про синглтон пишут:
Это поэтому ты сказал, что
|
| Автор: ekr 19.6.2007, 22:20 | ||
| Hi all. Коллеги, скажите, а к чему такие сложности? Может, я неправильно понял задачу... Но все же, зачем с помощью сериализации, выстраивания вызовов в очередь организовывать лишний bottleneck (здесь я согласен с Stampede)? На мой взгляд можно так сделать: пользователь проводит свои активности, накапливая изменения. Затем в финальном методе (когда юзер даст сигнал) просто получать соединение из пула, и в рамках транзакции модифицировать базу.
Логика сохранения будет выполняться в многопоточном режиме, эт точно. Но соединение с БД будет персональным для треда, и транзакция тоже. Так что БД должна будет изолировать транзакции друг от друга. Вот для этого надо будет почитать про уровни изоляции транзакций ))), узнать, поддерживается ли нужный в данной СУБД и установить его. Вот если СУБД не сможет внятно изолировать транзакции, тогда уже надо будет сериализовать (выстраивать в последовательность) операции средствами бизнес-логики, т.е. см. советы nornad, MisterCleric. |
| Автор: Stampede 20.6.2007, 00:31 | ||
Есть один нюанс. Поскольку транзакция включает выборки, можно предположить, что результаты этих выборок так или иначе будут использованы в операциях вставки. Если при этом не выставить уровень изоляции в SERIALIZED, есть немалый шанс нахватать фантомных ридов (хотя, конечно, сильно зависит от характера запросов). А сериализовать всю транзакцию - это в данном контексте то же самое, что синхронизовать бизнес-метод. Как лучше - это уже больше вопрос того, как мы собираемся управлять конкурентным доступом: программно или средствами базы. Есть мнение, что программно будет погибче, но при этом сложнее (и соответственно с большей вероятностью ошибок в логике) в реализации. А вообще при такой ожидаемой загрузке (20-30 транзакций в секунду), возможно, придется смотреть в сторону более "взрослых" решений типа EJB. Добавлено через 6 минут
Нет, в книжке скорее всего имеется в виду, что при запуске проги/старте контейнера может возникнуть ситуация, когда разные потоки начнут получать у себя экземпляр синглтона, а он еще толком не инициализирован. В данном случае на это счет можно особо не волноваться, ибо контейнер не допустит прихода запросов до тех пор, пока контекст не закончит инициализацию. |
| Автор: Zamuta 20.6.2007, 01:32 |
| Stampede, после твоих ответов у меня не остаётся вопросов, всё доходчиво. Это плюс. |
| Автор: ekr 20.6.2007, 09:08 | ||||||
Действительно, надо посмотреть на специфику запросов. Но так же надо учитывать, какие уровни изоляции реально поддерживает выбранная СУБД. Не все могут обеспечить SERIALIZABLE. А как еще её можно сериализовать? СУБД изолирует транзакции друг от друга целиком. С переменным успехом )))) В зависимости от выбранного уровня изоляции. Можно, конечно натыкать savepoints, но это уже тема отдельной долгой беседы )))
На мой взгляд - лучше выбрать нормальную СУБД и ей доверить Родину )))
Программно так же сложнее в поддержке, при изменениях. Стоимость разработки увеличивается, согласен. Вот здесь надо осторожно. Стоимость входа в эту технологию довольно высока (собственно разработка, обучение). Да, есть чудные бонусы, но надо сесть и внимательно посчитать, стоИт ли оно того. Бонусы, которые в данном случае могут помочь (но не решить проблему целиком): распределенные транзакции и Entity EJB. |