|
|
|
Thread-safe работа с БД через jdbc
|
|||
|---|---|---|---|
|
#18+
Есть большое количество однотипных потоков, которые живут недолго время и выполняют две задачи: 1) Отправляют XML-RPC запрос 2) Данные из ответа на XML-RPC запрос сохраняют в БД (Postgresql 8.1) Проблему я вижу в следующем. Все потоки используют один и тот же экземпляр класса Connection для создания Statement и выполнения запроса на insert, какие могут быть последствия? Интересно распишите плиз кто знает. Пути решения я вижу следующие, но не знаю какой выбрать: 1) Объявить метод который выполняет сохранение как synchronized, это вроде проблему решает но плохо, т.к. остальные потоки будут блокироватся, пока один сохраняет - в моем случае недопустимо 2) Использовать пул коннектов, например proxool, и дать каждому потоку свой экземпляр Connection 3) Организовать очередь. Т.е. поток помещает в результат в очередь и тут же завершается, а далее отдельный трэд потихоньку вытаскивает элементы из очереди и кладет в БД. Как лучше сделать и почему? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.03.2007, 14:52:53 |
|
||
|
Thread-safe работа с БД через jdbc
|
|||
|---|---|---|---|
|
#18+
cooluser Как лучше сделать и почему? 3. - Что может быть проще ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.03.2007, 15:02:06 |
|
||
|
Thread-safe работа с БД через jdbc
|
|||
|---|---|---|---|
|
#18+
Вариант 4 первый тред: XML-RPC запрос->ответ в очередь второй тред: ответ из очереди в бд и никаких пулов ненадо. зы доступ к очереди синхронизировать просто один читатель-один писатель ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.03.2007, 15:04:19 |
|
||
|
Thread-safe работа с БД через jdbc
|
|||
|---|---|---|---|
|
#18+
zalexakaВариант 4 читать: Вариант 3 конешно :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.03.2007, 15:08:47 |
|
||
|
Thread-safe работа с БД через jdbc
|
|||
|---|---|---|---|
|
#18+
ага спасибо за ответы :) а если не синхронизировать ничего и дать всем потокам один экземпляр Connection какие грабли можно поиметь? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.03.2007, 15:15:28 |
|
||
|
Thread-safe работа с БД через jdbc
|
|||
|---|---|---|---|
|
#18+
cooluser... Все потоки используют один и тот же экземпляр класса Connection для создания Statement и выполнения запроса на insert, какие могут быть последствия? Интересно распишите плиз кто знает. ... Весеннее обострение , што ли... По вопросу что лучше. Протестируйте. Я не удивлюсь если 3-й вариант не будет лучшим в вашем случае (BTW, что для вас "лучше"? вначале определитесь). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.03.2007, 15:16:35 |
|
||
|
Thread-safe работа с БД через jdbc
|
|||
|---|---|---|---|
|
#18+
Естественно я все протестирую и проверю... Мне было интересно мнение народа, вот я и пришел на форум, и ничего страшного в этом не вижу :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.03.2007, 16:56:53 |
|
||
|
Thread-safe работа с БД через jdbc
|
|||
|---|---|---|---|
|
#18+
"Организовать очередь. Т.е. поток помещает в результат в очередь и тут же завершается, а далее отдельный трэд потихоньку вытаскивает элементы из очереди и кладет в БД." Тут не все просто, если я правильно понял то, что Вы предлагаете, то поток, положивший результат в очередь "не имеет права" считать, что результат действительно записан в базу, т.к. еще всякое может случиться. Это допустимо? Любой сбой в очереди, при общении с самой базой, может потребовать неоднозначной реакции в зависимости от причин сбоя, важности данных и, главное, насколько сам поток готов к обработке такого сбоя и не зависит ли это от времени сбоя. Запись пакетов данных, конечно лучше чем одиночная, но и любой сбой в пакете потребует четко продуманной логики дальнейших действий. В общем и целом, устойчивости системе это не добавит. Я не знаю как обстоят дела с Postgress, но в том же Oracle не так просто получить проблемы с производительностью чтобы это начало сказываться на приложении - вы уверены, что у вас так много потоков и так часты запросы на обновления, что это РЕАЛЬНО приведет к деградации производительности СУБД? В общем-то вариант я не отвергаю, но при важных данных я бы рассмотрел вариант synchronized метода в отдельной триаде, пишущего на локальный диск (циклическая очередь из двух-трех файлов), т.е. имеем своеобразную самопальную транзакционную систему. Легко масшатабируется возможностью запуска нескольких триад. К этим файлам цепляется демон, который читает данные из локального файла/ов и пишет в базу пакетами. (Думаю хватит одного). Вариант не намного отличающийся от пула соединений, но переносит немалую часть нагрузки на клиента, возможно это будет более приемлемо. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.03.2007, 18:39:41 |
|
||
|
Thread-safe работа с БД через jdbc
|
|||
|---|---|---|---|
|
#18+
Стоп. Если мы не будем использовать пул соединений, то БД всегда будет думать, что к нему обращается только 1 поток, через 1 коннекшен. Значит она не сможет правильно оптимизировать свою работу. Так? Может, она захочет паралельно выполнять запросы, если имеются несколько коннекшинов? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.03.2007, 18:49:59 |
|
||
|
Thread-safe работа с БД через jdbc
|
|||
|---|---|---|---|
|
#18+
Может пул и не так сложно организовать например с помощью этого ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.03.2007, 18:52:07 |
|
||
|
Thread-safe работа с БД через jdbc
|
|||
|---|---|---|---|
|
#18+
carper ... Я не знаю как обстоят дела с Postgress, но в том же Oracle не так просто получить проблемы с производительностью чтобы это начало сказываться на приложении - вы уверены, что у вас так много потоков и так часты запросы на обновления, что это РЕАЛЬНО приведет к деградации производительности СУБД? PostgreSQL достаточно продвинутая и должна сама отпахать все эти проблемы, однако. Чоб я добавил, это некий MAX_INSERT параметер. Кажный, кто начинает писать, увеличивает счетчик. Те, кто закончил - уменьшает его. Если счетчик дошел до MAX_INSERT, просто ждем или отваливаем ... Это самый простой вариант (свалить типа все на базу). С ораклом я так бы и поступил. С Postgre можно тоже попробовать и посмотреть. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.03.2007, 18:54:20 |
|
||
|
Thread-safe работа с БД через jdbc
|
|||
|---|---|---|---|
|
#18+
carper"Организовать очередь. Т.е. поток помещает в результат в очередь и тут же завершается, а далее отдельный трэд потихоньку вытаскивает элементы из очереди и кладет в БД." Тут не все просто, если я правильно понял то, что Вы предлагаете, то поток, положивший результат в очередь "не имеет права" считать, что результат действительно записан в базу, т.к. еще всякое может случиться. Это допустимо? Да, в моем случае это действительно допустимо, т.к. по сути это вспомогательная утилита и потоку действительно достаточно действовать на уровне поместил данные для сохранения в очередь или еще куда и отвалился. Ну и плюс вероятность что случится что то с СУБД или сетью очень мала. А вообще вы конечно интересный аспект подняли, подумаю на досуге обязательно над этим, единственное что вариант с самопальными файлами на диске мне априори не нравится, все таки работа с данными - дело СУБД. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.03.2007, 20:20:02 |
|
||
|
Thread-safe работа с БД через jdbc
|
|||
|---|---|---|---|
|
#18+
PostgreSQL достаточно продвинутая и должна сама отпахать все эти проблемы, однако. Чоб я добавил, это некий MAX_INSERT параметер. Кажный, кто начинает писать, увеличивает счетчик. Те, кто закончил - уменьшает его. Если счетчик дошел до MAX_INSERT, просто ждем или отваливаем ... Это самый простой вариант (свалить типа все на базу). С ораклом я так бы и поступил. С Postgre можно тоже попробовать и посмотреть. Как то развлекался в postgresql следующим образом, делал простенькую табличку на 5 полей целых и строковых типов, делал питоновский скрипт который в 40 потоков insert'ил данные в эту табличку, работало это дело по нескольку часов, абсолютно все insert'ы проходил без проблем. Сейчас написал и подумал...почему то когда делал это тестовый скрипт на питоне абсолютно не задумывался над проблемой thread-safe и прочего. Там помоему был один общий конекшн на всех, и ведь отрабатывало нормально. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.03.2007, 20:25:16 |
|
||
|
Thread-safe работа с БД через jdbc
|
|||
|---|---|---|---|
|
#18+
2 carper Еще раз прочитал ваше сообщение. Вообщем получается что потоку достаточно отдать данные для дальнешей обработки куда то, что с ними дальше происходит его не волнует. А вот уже трэд обслуживающий очередь, в случае ошибок при сохрании данных, должен просто повторять до победного конца (возможно надо все таки лимитировать количество попыток). Вроде как при таком подходе будет гарантия сохрания данных, ну конечно если JVM не упадет. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.03.2007, 20:32:43 |
|
||
|
Thread-safe работа с БД через jdbc
|
|||
|---|---|---|---|
|
#18+
Уважаемые, может тогда и JMS прикрутить? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.03.2007, 22:13:58 |
|
||
|
Thread-safe работа с БД через jdbc
|
|||
|---|---|---|---|
|
#18+
cooluser2 carper Еще раз прочитал ваше сообщение. Вообщем получается что потоку достаточно отдать данные для дальнешей обработки куда то, что с ними дальше происходит его не волнует. А вот уже трэд обслуживающий очередь, в случае ошибок при сохрании данных, должен просто повторять до победного конца (возможно надо все таки лимитировать количество попыток). Вроде как при таком подходе будет гарантия сохрания данных, ну конечно если JVM не упадет. Увы, гарантию может дать только сама база. :) Если сохранность данных не столь важна, то, разумеется, можно передавать данные в буфер сервисного потока (можно нескольких, в тяжелых случаях), который единообразным способом пытается их записать. Я бы дополнительно сделал эти данные адресными, снабдив каждую строку в буфере GUID потока, их туда пославшего. Скорее всего алгоритм должен предусматривать несколько попыток записи (очень немного иначе теряется всякий смысл использования дополнительного служебного потока - вы в базу напрямую быстрее запишете), с сбросом дефектных данных либо в лог, либо вообще к такой-то матери. Тут возникает один незатык - мы априори считаем, что производительности самой базы не хватает, чтобы обеспечить прямую запись данных из потоков, если мы используем буфер, то мы можем поднять производительность в основном за счет пакетной записи (я так понимаю, что все потоки пишут в одно и то же место данные одинаковой структуры?). Так? Но тогда узким местом становится сам буфер и пакетная запись, т.е. проблема никуда не исчезает, она просто несколько отодвигается, плюс возникает проблема с оперативкой в которой должен лежать сам этот буфер, она ведь тоже не резиновая. Опять же, я не знаю особенностей Postgresql, но Oracle умеет решать эту проблему - она как раз использует и демоны и запись во временные файлы и их очередь. Т.е. стоит ли городить огород, чтобы своими силами реализовать то, что уже есть? Если количество потоков (точнее частота записи) нешуточное, то непрерывно что-то дергать в базе, действительно, варварство, а если нет, то может ну его? P.S. В принципе, я бы тут думал не над техническим решением, а над тем почему надо писать в базу столько данных, что она начинает аж захлебываться, причем не очень важно чтобы записались все данные. Что-то тут не так. Может быть нужны какие-то краткосрочные тренды, для вывода оперативной информации с совсем даже не частой записью некоторых итоговых, усредненных, или как-то еще обсчитанных, данных? Зачем вам тысячи и миллионы строк, для которых даже не очень важно все ли они записаны? Что вы с ними дальше-то делать собираетесь? Очевидно, что просматривать их никто не будет, будут делаться какие-то обобщающие выборки. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.03.2007, 09:56:15 |
|
||
|
|

start [/forum/topic.php?fid=59&msg=34387508&tid=2146397]: |
0ms |
get settings: |
14ms |
get forum list: |
30ms |
check forum access: |
8ms |
check topic access: |
8ms |
track hit: |
64ms |
get topic data: |
24ms |
get forum data: |
7ms |
get page messages: |
110ms |
get tp. blocked users: |
4ms |
| others: | 302ms |
| total: | 571ms |

| 0 / 0 |
