Стратегии и методы настройки подключения к базе данных

база данных

Введение

Соединение с базой данных играет важную роль в процессе выполнения приложением SQL-запроса. Особенно, когда речь идет о внезапном всплеске трафика, необходимости создания большого количества подключений или сбое в сети, приводящем к повторному подключению, с точки зрения бизнеса выполнение SQL замедляется.В настоящее время выполнение SQL не очень медленное. Эта статья основана на передовом опыте Durid в нашей собственной производственной среде и предназначена только для справки.Конечно, давление связи/бизнеса у разных компаний может быть разным. К конкретным параметрам нужно относиться по-разному.

Две особые практики

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

2.1 Как установить размер пула соединений

Соответствующий размер пула соединений и количество запросов в секунду для бизнес-запросов и RT для одного запроса (в миллисекундах). Основная формула:

Количество подключений = QPS /(1000/RT) + N = QPS * RT /1000 + N

Примечание. Здесь QPS и RT — статистика одного приложения. Предполагается, что количество запросов, которые может обработать клиент, увеличивается линейно по мере увеличения количества подключений.

Например

比如 一个请求的耗时rt=2ms,每个连接能处理的请求数量 

S = 1000/2 =500 ,

业务层总请求量是 M=5000 ,那么合理的连接数为 

M/S=5000/500=10 

为了避免连接数被占满,我们会在上面的连接数的基础上再加上N ,最终的连接数为10+N .

Рассчитайте обычные максимальные QPS и RT в это время, чтобы вычислить minIdle, и установите initialSize = minIdle.

Рассчитайте QPS на пике и RT в это время, чтобы рассчитать maxActive.

Вы можете наблюдать за фактическим состоянием пула соединений Druid через jmx с помощью следующих методов, ориентируясь на ActiveCount: количество активных подключений и PoolingCount: количество подключений в пуле. И рассмотрим корректировку в соответствии с реальной ситуацией.

java -XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -Xverify:none -client -jar /PATH/cmdline-jmxclient-0.10.3.jar - 127.0.0.1:7777 'com.alibaba.druid:type=DruidDataSourceStat' DataSourceList |& grep -E 'ActiveCount|PoolingCount'

2.2 Как установить время ожидания

Тайм-ауты в пуле соединений в основном включают:

connectTimeout Тайм-аут для установления TCP-соединения

maxWait Максимальное время ожидания для получения соединения из пула соединений.

socketTimeout Время ожидания ответа после отправки запроса

в,connectTimeoutРекомендуется не менее 1200 мс. Когда TCP устанавливает соединение, время ожидания повторной передачи пакета SYN составляет 1 с. Если для параметра connectTimeout установлено слишком короткое время, это может привести к тайм-ауту из-за джиттера сети во время инициализации пула соединений, когда приложение выпущено, или если промежуточному сетевому устройству необходимо инициализировать состояние, чтобы инициировать тайм-аут из-за потери пакетов. , что приведет к сбою инициализации пула соединений и сбою выпуска.

socketTimeoutЕго можно установить в соответствии с максимальным временем возврата запроса приложения. Слишком длинный запрос вызовет проблемы с сетью или лавины при возникновении проблем со службами базы данных; слишком короткий вызовет частые тайм-ауты запросов. Не менее 300 мс. TCP имеет минимальное RTO 200 мс и динамически настраивается в зависимости от задержки. Слишком короткое время ожидания приведет к потере одного пакета, что приведет к истечению времени ожидания запроса. База данных производственной среды настроена с помощью SQL Killer, который автоматически уничтожает запросы, выполнение которых занимает слишком много времени. Поэтому ставить чрезмерно длинный socketTimeout тоже не имеет смысла.

maxWaitЕго можно установить в соответствии со временем ожидания, ожидаемым приложением. Во избежание лавин в случае сетевых проблем или проблем с базой данных, это время не должно быть слишком большим. Значение по умолчанию 800 мс ниже является консервативной настройкой. Приложение может установить более короткое время, например 300 мс. Если время слишком короткое, количество соединений в пуле соединений будет недостаточным, что приведет к большому количеству тайм-аутов, когда потребуются новые соединения. Рекомендуется не менее 100 мс.

2.3 Как установить время удержания соединения

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

App -> LVS -> Proxy -> DB

Путь доступа к RDS: App -> LVS -> Proxy.

Среди них время удержания незанятого соединения LVS составляет 90 с. Чтобы избежать доступа к закрытому соединению, прокси удерживает собственное незанятое соединение в течение [70, 85) с. Поэтому, чтобы избежать получения закрытых подключений из пула подключений, приложение должно настроить себя на сохранение неактивных подключений не более 70 с. Эффект после включения KeepAlive

Когда пул соединений инициализирован, он будет заполнен до количества minIdles.

Подключения в пределах количества minIdles в пуле подключений, время простоя превышает

minEvictableIdleTimeMillis будет выполнена операция keepAlive.

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

timeBetweenEvictionRunsMillis=10000, 

minEvictableIdleTimeMillis=44000, 

maxEvictableIdleTimeMillis=55000。

2.4 Необходимые элементы конфигурации

Следующие конфигурации по умолчанию могут быть скорректированы в соответствии с реальной ситуацией.

<bean id="cartDataSource" class="com.alibaba.druid.pool.DruidDataSource"
          init-method="init" destroy-method="close">
        <property name="url" value="${cluster.jdbc.url}"/>
        <property name="username" value="${cluster.jdbc.username}"/>
        <property name="password" value="${cluster.jdbc.password}"/>
        <property name="connectionInitSqls" value="set names utf8mb4"/>
        <!-- 连接池初始连接数 -->
        <property name="initialSize" value="5" />
        <!-- 允许的最大同时使用中(在被业务线程持有,还没有归还给druid) 的连接数 -->
        <property name="maxActive" value="20" />
        <!-- 允许的最小空闲连接数,空闲连接超时踢除过程会最少保留的连接数 -->
        <property name="minIdle" value="5" />
        <!-- 从连接池获取连接的最大等待时间 800毫秒;业务方根据可以自行调整-->
        <property name="maxWait" value="800" />
        <!-- 一条物理连接的最大存活时间 120分钟-->
        <property name="phyTimeoutMillis" value="7200000"/>
        <!-- 强行关闭从连接池获取而长时间未归还给druid的连接(认为异常连接)-->
        <property name="removeAbandoned" value="true"/>
        <!-- 异常连接判断条件,超过180 秒 则认为是异常的,需要强行关闭 -->
        <property name="removeAbandonedTimeout" value="180"/>
        <!-- 从连接池获取到连接后,如果超过被空闲剔除周期,是否做一次连接有效性检查 -->
        <property name="testWhileIdle" value="true"/>
        <!-- 从连接池获取连接后,是否马上执行一次检查 -->
        <property name="testOnBorrow" value="false"/>
        <!-- 归还连接到连接池时是否马上做一次检查 -->
        <property name="testOnReturn" value="false"/>
        <!-- 连接有效性检查的SQL -->
        <property name="validationQuery" value="SELECT 1"/>
        <!-- 连接有效性检查的超时时间 1 秒 -->
        <property name="validationQueryTimeout" value="1"/>
        <!-- 周期性剔除长时间呆在池子里未被使用的空闲连接, 10秒一次-->
        <property name="timeBetweenEvictionRunsMillis" value="10000"/>
        <!-- 空闲多久可以认为是空闲太长而需要剔除 44 秒-->
        <property name="minEvictableIdleTimeMillis" value="44000"/>
        <!-- 如果空闲时间太长即使连接池所剩连接 < minIdle 也会被剔除 55 秒 -->
        <property name="maxEvictableIdleTimeMillis" value="55000"/>
        <!-- 是否设置自动提交,相当于每个语句一个事务 -->
        <property name="defaultAutoCommit" value="true"/>
        <!-- 记录被判定为异常的连接 -->
        <property name="logAbandoned" value="true"/>
        <!-- 网络读取超时,网络连接超时
             socketTimeout : 对于线上业务小于5s,对于BI等执行时间较长的业务的SQL,需要设置大一点
        -->
        <property name="connectionProperties" value="socketTimeout=3000;connectTimeout=1200"/>
        <property name="proxyFilters">
            <list>
                <ref bean="log-filter"/>
            </list>
        </property>
</bean>

После версии 1.0.28 вновь добавлена ​​конфигурация keepAlive, которая по умолчанию отключена. Для использования функции keepAlive рекомендуется использовать версию 1.1.16 или выше. Общие службы открывать не нужно, за исключением случаев, когда минутный объем запросов выражается однозначным числом или время запуска слишком велико, чтобы истечь срок действия исходного соединения.

2.5 друид версия

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

например, конфигурация Maven:

  <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.0.27</version>
  </dependency>

Три сводки

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

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