Подробное объяснение пула подключений к базе данных Druid
Подробное объяснение пула подключений к базе данных Druid

В проектах Spring Boot пулы соединений с базами данных стали стандартными. Однако я сталкивался со многими случаями, когда исключения пула соединений приводили к бизнес-ошибкам. У многих опытных инженеров случайно могут возникнуть проблемы в этой области.

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

1 Зачем нужен пул соединений?

Если пула соединений нет, наш процесс работы с базой данных выглядит следующим образом:

  1. Приложение, использующее базу сборка драйвера данных ибаза данныхиз TCP соединять ;
  2. Пользователь проходит аутентификацию;
  3. После прохождения проверки личности приложение выполняет операции чтения и записи;
  4. После завершения операции закройте TCP соединять 。

Создание подключения к базе данных является относительно дорогостоящей операцией. Если в сети одновременно находятся сотни или даже тысячи людей, частые операции подключения будут занимать больше системных ресурсов. Однако количество подключений, поддерживаемых базой данных, ограничено, и оно ограничено. возможно создание большого количества подключений. Приведет к зависанию базы данных.

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

Напротив, преимущества пула соединений очевидны:

1. Повторное использование ресурсов:

Поскольку соединения с базой данных можно использовать повторно, можно избежать больших затрат на производительность, вызванных частым созданием и освобождением соединений, а также повысить стабильность операционной среды системы.

2. Улучшите производительность

Когда делается бизнес-запрос, поскольку соединение с базой данных было создано во время инициализации, его можно использовать немедленно, не дожидаясь установления соединения, что сокращает время ответа.

3. Оптимизируйте распределение ресурсов

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

4. Управление подключением

При реализации пула соединений с базой данных занятые соединения могут быть принудительно перезапущены в соответствии с предварительно заданным значением тайм-аута, что позволяет избежать утечки ресурсов, которая может возникнуть при обычных операциях подключения к базе данных.

2 пула соединений JDBC

Следующий код показывает процесс работы базы данных JDBC:

Язык кода:javascript
копировать
//1. соединятьприезжатьбаза данных
Connection connection = DriverManager.getConnection(jdbcUrl, username, password);
//2. Выполнить SQL-запрос
String sqlQuery = "SELECT * FROM mytable WHERE column1 = ?";
PreparedStatement preparedStatement = connection.prepareStatement(sqlQuery);
preparedStatement.setString(1, "somevalue");
resultSet = preparedStatement.executeQuery();
//3. Обработка результатов запроса
while (resultSet.next()) {
    int column1Value = resultSet.getInt("column1");
    String column2Value = resultSet.getString("column2");
    System.out.println("Column1: " + column1Value + ", Column2: " + column2Value);
}
//4. закрыть ресурс
resultSet.close();
preparedStatement.close();
connection.close();

Вышеупомянутый метод часто создает соединения с базой данных и иногда используется на старых страницах JSP. В настоящее время широко используется пул соединений JDBC.

JDBC пул соединений Есть стандартиз Интерфейс источника данныхjavax.sql.DataSource,Этот класс находится в Java в библиотеке библиотеки.

Язык кода:javascript
копировать
public interface DataSource  extends CommonDataSource, Wrapper {

  Connection getConnection() throws SQLException;

  Connection getConnection(String username, String password) throws SQLException;
}

Обычно используемые пулы соединений JDBC:

  • HikariCP
  • C3P0
  • Druid

Druid (Пул подключений к базе данных Alibaba) — это библиотека пулов подключений к базе данных с открытым исходным кодом, которая обеспечивает мощные функции управления и мониторинга пула подключений к базе данных.

1. Настройте источник данных Druid.

Язык кода:javascript
копировать
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl("jdbc:mysql://localhost:3306/mydatabase");
dataSource.setUsername("yourusername");
dataSource.setPassword("yourpassword");
dataSource.setInitialSize(5); // Начальный пул соединенийразмер
dataSource.setMinIdle(5); // Минимальное количество неактивных соединений
dataSource.setMaxActive(20); // Максимальное количество действий, соединяющихся
dataSource.setValidationQuery("select 1 from dual");  // сердцебиение Query
dataSource.setMaxWait(60000); // максимальное время ожидания
dataSource.setTestOnBorrow(true); // Убедитесь, что соединение действительно

2. Используйте подключение к базе данных.

Язык кода:javascript
копировать
Connection connection = dataSource.getConnection();
//использоватьсоединятьосуществлятьбаза данныхдействовать
// TODO деловые операции
// Закрыть после использования
connection.close();

3. Закройте источник данных.

Язык кода:javascript
копировать
dataSource.close();

3 Принцип реализации пула соединений Druid

Реализация нашего источника обучающих данных может быть проанализирована со следующих пяти основных точек зрения:

  • инициализация
  • Создать соединение
  • Перезагрузочное соединение
  • обратное соединение
  • уничтожить соединение

3.1 Инициализация

Сначала мы рассмотрим реализацию источника данных.「Получить соединение」из Скриншот интерфейса,инициализация Можетинициативаипассивныйдва пути。

Master-slave относится к явному вызову метода init, тогда как

вызовgetConnectionметодчас,возвращатьсяизобъектдасоединятьинтерфейсиз Класс инкапсуляции DruidConnectionHolder

В рамках метода инициализации источник данных создает три массива пулов соединений.

  • connections:Используется для хранения и полученияизсоединятьобъект。
  • evictConnections:Используется для хранения и подлежит утилизации.изсоединятьобъект。
  • keepAliveConnections:Используется для хранения и должен быть сохранен в живыхизсоединятьобъект。

для этапа инициализации требуется пул соединенийизподогреть:也就дануждаться按照配置первый创建一定число量изсоединять,и положить его в бассейн,Подать заявку вот таксуществоватьнуждаться Получить соединение, может быть получено непосредственно из пула.

источник данных「подогреть」разделен насинхронныйиасинхронныйдва пути , см. картинку ниже:

На рисунке выше мы видим, что при синхронном создании соединения собственный JDBC создает соединение и помещает его непосредственно в объект массива соединений. Асинхронное создание потоков требует инициализации createScheduler, но он не настроен по умолчанию.

источник данныхподогретьпосле,Запускаются два потока задач:Создать соединениеиуничтожить соединение

3.2 Создать соединение

В этом разделе мы сосредоточимся на изучении Druid источник данных如何Создать соединение

CreateConnectionThread Суть в том, что один поток проходит в бесконечном цикле. condition Ожидание, пробуждённое другими потоками и реализовать логику создания подключения к базе данных.

Автор соответствующим образом упростил метод запуска. При выполнении условий создается соединение с базой данных:

  • Необходимо сохранить тему, чтобы дождаться создания. соединение
  • Запретить создание числа подключений, превышающего максимально допустимое. maxAcitve

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

3.3 Получить соединение

Мы подробно разобрали процесс создания соединения, и следующим шагом будет процесс получения соединения приложением.

DruidDataSource#getConnection Метод будет называться DruidDataSource#getConnectionDirect Способ получения соединения реализуется следующим образом.

Основной процесс – это

1. в for Внутри цикла первый вызов getConnectionDirectВнутри,вызовgetConnectionInternal Получить объект подключения из пула;

2. После получения соединения необходимо testOnBorrowtestWhileIdle Конфигурация параметров определяет, необходимо ли определять достоверность соединения;

3. Наконец, если вам нужно определить, есть ли утечка соединения, настройте removeAbandoned Для закрытия соединений, которые были недоступны в течение длительного времени. Эта функция не рекомендуется для использования в производственных средах и используется только для обнаружения и диагностики утечек соединений.

Далее введите Tweet соединениеизфокус:getConnectionInternal Как получить соединение из пула.

getConnectionInternal()методсередина拿приезжатьсоединятьиз Есть три способа:

  1. прямой Создать соединение (конфигурация по умолчанию не будет выполнена) Необходимо настроить пул потоков синхронизации createScheduler,당пул соединений нет доступных соединений, и текущее количество кредитов изоединять не достигло максимально допустимого количества, и в настоящее время нет других потоков. Создать существование. соединение ;
  2. pollLast метод:взять из бассейнасоединять,и ждать максимум maxWait изчас间,нуждаться设置了maxWait

Суть метода pollLast заключается в следующем: внутри бесконечного цикла ожидание выполняется с помощью метода awaitNanos объекта Condition notEmpty. Если в пуле есть соединение, последнее соединение удаляется и последний элемент массива устанавливается пустым. .

  1. takeLast метод:взять из бассейнасоединять,И подождите, пока у вас получится подключиться.

и опрос Последний методразные,первыйметод体Внутри部Нет бесконечного цикла,проходить Condition объект notEmpty из await Метод ждет, пока в пуле появится соединение, удаляет последнее соединение и устанавливает пустой элемент последнего элемента массива.

3.4 Обратное соединение

DruidDataSource пул В соединениях каждое физическое соединение будет заменено на вложенное. вDruidConnectionHolder,существование предоставляется потоку приложения до,также будет DruidConnectionHolder упакованный в DruidPooledConnection

Родной из JDBC действовать, 每次осуществлять完деловые операциипосле,Выполнит выключение соединения,дляпул соединений Давайте поговорим,就даобратное соединение, то есть вернуть соединение обратно в пул соединений

На рисунке ниже показано DruidPooledConnection из close метод :

существоватьзакрытиеметодсередина,我们фокуссосредоточиться на recycle Перезагрузочное соединениеметод。

Мы можем понять это просто: поместите соединение в connections Массив из poolingCount позицию и увеличьте ее, затем передайте Condition объект notEmpty Просыпайся, ожидая соединение приложения.

3.5 Уничтожить соединение

DruidDataSource соединятьиз销毁 DestroyConnectionThread Тема завершена :

Каждый раз из запланированной задачи (бесконечный цикл) timeBetweenEvictionRunsMillis Выполнив один раз, мы фокусируем внимание наdestroyTaskизrunметод。

destroyTaskизrunметод 会вызовDruidDataSource#shrinkметодустановить согласноиз条件来判断出нуждаться销毁идетский садизсоединять。

Основной процесс:

1. Обход массива пула соединений connections

​ Внутренне определите, нужно ли разрушать эти связи или сохранять их живыми. ,并分别加入приезжать对应изв массиве контейнеров。

2. Уничтожить сцену

  • свободное времяidleMillis >= Разрешенный минимум свободного времени время minEvictableIdleTimeMillis
  • свободное времяidleMillis >= Разрешено максимальное свободное время время maxEvictableIdleTimeMillis

3. Сцена ухода за детьми

  • Произошла фатальная ошибка (onFatalError == true)且致命错误发生час间(lastFatalErrorTimeMillis)существоватьсоединять建立час间после
  • Если механизм поддержания активности включен и подключатьсвободное время больше или равно интервалу поддержания активности

4、уничтожить соединение

​ Траверсный массив evictConnections Все изоединять и уничтожать один за другим 。

5. Поддерживайте живое соединение

​ Траверсный массив keepAliveConnections Все изоединять, проверить соединение , если проверка не пройдена, соединение будет закрыто, в противном случае оно будет заблокировано и повторно добавлено в пул соединений.

4 Убедитесь, что соединение действительно

В этом разделе мы объясним, как правильно настроить параметр, чтобы обеспечить эффективность базы данныхсоединять.

Многие студенты сталкиваются с проблемой: «После длительного невыполнения операций чтения и записи в базу данных база данных при первом запросе к базе данных сообщит об ошибке, но во второй раз все будет нормально».

那да因为В целях экономии ресурсов база данных будет закрыта, если она долгое время не читалась и не записывалась изоединять

Автор использует его впервые Druid Я столкнулся с такой проблемой в молодости. Если вам интересно, вы можете прочитать эту статью:

https://www.javayong.cn/codelife/runningforcode.html

На рисунке ниже показано Druid Пример конфигурации источника данных:

Подведем краткий итог Druid из Убедитесь, что соединение действительно Каковы стратегии:

1、уничтожить Поток соединения регулярно обнаруживает все изоединять и закрывает остальные время Слишком большойизсоединять ,Если параметр Keepalive настроен,Тогда его будут продолжать поддерживать, чтобы сохранить изоединять;

2. Приложение каждый раз извлекает данные из источника данных. соединениечас候,будет основано наtestOnBorrowtestWhileIdleпараметр Обнаружениесоединятьизэффективность。

Поэтому нам нужно сосредоточиться на следующей конфигурации:

A、timeBetweenEvictionRunsMillis – параметр:间隔多久Обнаружение一次空闲соединятьда否有效。

B. Параметр testWhileIdle:Запуск на холостом ходусоединятьиз Обнаружение,Настоятельно рекомендуется установить для этого параметра значение true.

C. Параметр minEvictableIdleTimeMillis:пул соединенийсерединасоединятьмаксимумсвободное время(миллисекунда),соединятьчисло > minIdle && свободное время > minEvictableIdleTimeMillis 。

D. Параметр maxEvictableIdleTimeMillis:пул соединенийсерединасоединятьмаксимумсвободное время,свободное время > maxEvictableIdleTimeMillis, независимо от пула Является ли количество изоединений в соединениях меньшим, чем минимальное количество соединений? 。

E. параметр testOnBorrow:включатьсоединятьиз Обнаружение,Получить Проверьте, действительно ли оно действует при соединении, если установлено значение true , что может гарантировать надежность в наибольшей степени, но производительность станет очень низкой. 。

Автор рекомендует существовать при настройке этих параметров, и DBA и архитекторы должны связаться заранее, каждая компания избаза Стратегии конфигурации данных не совпадают, если база Время выживания конфигурации соединения данных очень короткое, тогда необходимо соответствующим образом уменьшить интервал обнаружения простоя соединения и снизить максимальное и минимальное время работы. время。

5 Резюме

В этой статье автор собрал знания по базе данных пулиз соединений.

1、пул соединенийизпреимущество:Повторное использование ресурсов、Улучшите производительность、Оптимизировать распределение ресурсов、соединятьуправлять;

2、JDBC пул соединений:实现Интерфейс источника данныхjavax.sql.DataSource,Этот класс находится в стандартной библиотеке Java;

3. Пул соединений Druid Принцип реализации

  • основнойметод:инициализация、Создать соединение、Получить соединение、обратное соединение、уничтожить соединение。
  • Контейнер хранения: массив соединений пула, массив соединений уничтожения, массив поддержания активности соединения.
  • Модель потоков: независимая из Создать нить соединения иуничтожить нить соединения.
  • механизм замка:существовать Создать соединение、Получить соединение, будет заблокировано через два Condition объект emptynotEmpty Управление Создать индивидуально соединениенитьи Получить Поток соединения из ожидания и пробуждения.

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

Автор даст вам подробное объяснение в следующей статье:

  1. Как использовать структуру пула Commons Pool
  2. Netty Как добиться простоты изпул соединений。

Справочная статья:

https://segmentfault.com/a/1190000043208041 https://blog.csdn.net/weixin_43790613/article/details/133940617 https://blog.csdn.net/yaomingyang/article/details/123145662


boy illustration
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose