Golang sobre la implementación del grupo de conexiones Mysql

Prefacio

A medida que aumenta el volumen de negocios, inevitablemente encontrará problemas de rendimiento de la base de datos. Desde declaraciones SQL razonables, índices de campos, subbases de datos y tablas, separación de lectura y escritura, etc., junto con la tecnología de almacenamiento en caché, básicamente puede resolver casi todos los negocios. Es suficiente con actualizar el hardware, y el propio Go ha implementado un pool de conexiones para solucionar el retraso provocado por la conexión y con ello mejorar el rendimiento (se intercambia espacio por tiempo), así que me gustaría saber cómo mejorarlo.

Descripción del parámetro MYSQL

Agrupación de conexiones : manteniendo un conjunto de conexiones de bases de datos en la memoria para que las conexiones se puedan asignar y liberar rápidamente cuando sea necesario. Esto evita la apertura y cierre frecuentes de conexiones de bases de datos, mejorando así la eficiencia y el rendimiento del sistema.

Por lo tanto, se almacena en la memoria en forma de una conexión larga y debe haber dos estados: ocupado/inactivo . En el estado inactivo, se debe considerar el tiempo de espera. Aparte del límite de tiempo de espera del propio cliente, habrá También habrá un límite de tiempo de espera en el servidor; la misma conexión Un grupo es un grupo, por lo que habrá muchas conexiones y el número correspondiente en la configuración también estará sujeto a limitaciones en el servidor.

Por lo tanto, antes de configurar el grupo de conexiones, debemos comprender la configuración de parámetros y funciones relevantes de mysql; de lo contrario, será contraproducente.

Campo Breve descripción Información adicional
conexión_max Número máximo de conexiones manejadas simultáneamente El valor predeterminado para este parámetro suele ser 100, pero se puede ajustar según las necesidades de configuración y rendimiento del servidor. Si el servidor alcanza el límite de max_connections, las nuevas solicitudes de conexión se rechazarán hasta que el número actual de conexiones caiga por debajo de max_connections. Por lo tanto, si su servidor encuentra con frecuencia errores de "Demasiadas conexiones", puede resolver este problema aumentando el valor de max_connections. Sin embargo, también tenga en cuenta que aumentar max_connections puede aumentar el consumo de recursos en el servidor, así que ajuste en consecuencia.
conexiones_extra_max Número máximo de conexiones aceptadas después de exceder el número máximo de conexiones Especifica el número máximo de conexiones que el servidor puede manejar simultáneamente. Si el servidor está ocupado y se ha alcanzado el límite de max_connections, el servidor ya no aceptará nuevas solicitudes de conexión hasta que aparezca una conexión inactiva. El parámetro extra_max_connections permite al servidor aceptar más solicitudes de conexión en circunstancias especiales para brindar más flexibilidad en situaciones de emergencia. Por ejemplo, si configura extra_max_connections en 10, el servidor aún puede aceptar 10 solicitudes de conexión adicionales después de que max_connections alcance el límite. Cabe señalar que el uso del parámetro extra_max_connections puede afectar el rendimiento del servidor, por lo que debe usarse cuando sea necesario.
tiempo de espera Tiempo máximo de espera después de una inactividad no interactiva Si la conexión no envía ninguna solicitud durante este período, MySQL desconectará la conexión. El valor predeterminado para este parámetro suele ser 8 horas, pero su valor se puede cambiar modificando el archivo de configuración. El propósito de este parámetro es evitar fugas de conexión, es decir, si una conexión permanece inactiva durante mucho tiempo, MySQL la desconectará para ahorrar recursos. Por supuesto, si su aplicación requiere una conexión a largo plazo, puede aumentar el valor de este parámetro de manera adecuada.

En la descripción de wait_timeout, no interactivo se refiere a la ejecución del código, mientras que el interactivo correspondiente se refiere al control de tiempo de espera interactivo, que se refiere a clientes como navicat que se conectan a la base de datos.
Esto se menciona porque cuando modificamos el valor correspondiente, si solo modificamos el primero, encontraremos que no hay ningún cambio (de hecho, ha surtido efecto) al imprimir los parámetros del sistema en el cliente. trastorno, puedes modificar ambos.

Oraciones relacionadas

-- 查询语句
SHOW VARIABLES LIKE '%max_connections';
SHOW VARIABLES LIKE 'wait_timeout%' ;
SHOW VARIABLES LIKE '%interactive_timeout%';

-- 设置全局变量
SET GLOBAL max_connections = 100;
SET GLOBAL wait_timeout = 10;
SET GLOBAL interactive_timeout = 10;

Ir a la descripción del grupo de conexiones

Configuración de parámetros del grupo de conexiones

=// 全局 db 对象
var DB *sql.DB

// ConnectionPool 连接池的学习
func ConnectionPool() {
    
    
	// 连接 db
	db, err := sql.Open("mysql", "root:123456@/db?charset=utf8")
	if err != nil {
    
    
		panic(err)
	}
	//defer db.Close()
	db.SetMaxOpenConns(100)                //   设置连接数总数, 需要根据实际业务来测算, 应小于 mysql.max_connection (应该远远小于), 后续根据指标进行调整
	db.SetMaxIdleConns(50)                 //  设置最大空闲连接数, 该数值应该小于等于 SetMaxOpenConns 设置的值
	db.SetConnMaxLifetime(0)               // 设置连接最大生命周期, 默认为 0(不限制), 我不建议设置该值, 只有当 mysql 服务器出现问题, 会导致连接报错, 恢复后可以自动恢复正常, 而我们配置了时间也不能卡住出问题的时间, 配置小还不如使用 SetConnMaxIdleTime 来解决
	db.SetConnMaxIdleTime(4 * time.Second) // 设置空闲状态最大生命周期, 该值应小于 mysql.wait_timeout 的值, 以避免被服务端断开连接, 产生报错影响业务, 一般可以配置 1天。

	// 赋值 db 对象
	DB = db
}

Ejemplo de error de tiempo de espera de conexión del servidor relacionado
Insertar descripción de la imagen aquí

Indicadores y descripciones de parámetros de grupos de conexiones en base de datos/sql

Indicadores de datos sobre DBStats

Campo ilustrar
MaxOpenConnections El número máximo de conexiones, MaxOpenConnections, establecido por SetMaxOpenConns
Conexiones abiertas El número total de conexiones activas, este valor no excederá el valor de MaxOpenConnections
En uso El número de conexiones en uso. Si ejecuta cerrar o escanear (con cerrar), la conexión será devuelta. De lo contrario, estará ocupada hasta que se agote el tiempo de conexión.
Inactivo Número de conexiones actualmente inactivas
Conteo de espera El número total de conexiones de bases de datos actualmente en espera.
Duración de la espera Tiempo para esperar la conexión a la base de datos
MaxIdleCerrado El número total de conexiones inactivas que se cerraron cuando el número de conexiones inactivas superó el límite está limitado por SetMaxIdleConns.
MaxIdleTimeCerrado El número total de conexiones inactivas cerradas debido al tiempo de espera, limitado por SetMaxIdleTime
MaxLifetimeCerrado El número total de conexiones cerradas debido al tiempo de espera, limitado por SetMaxLiftTime

método de llamada

func getDbStats(w http.ResponseWriter, r *http.Request) {
    
    
	info := fmt.Sprintf("最大连接数:%d,  当前总连接数;%d,  已使用: %d, 空闲数量:%d \n", DB.Stats().MaxOpenConnections, DB.Stats().OpenConnections, DB.Stats().InUse, DB.Stats().Idle)
	info2 := fmt.Sprintf("数量指标 :) \n等待连接数量;%d,  等待创建新连接时长(秒): %f, 空闲超限关闭数量:%d, 空闲超时关闭数量:%d, 连接超时关闭数量:%d \n",
		DB.Stats().WaitCount,
		DB.Stats().WaitDuration.Seconds(),
		DB.Stats().MaxIdleClosed,
		DB.Stats().MaxIdleTimeClosed,
		DB.Stats().MaxLifetimeClosed,
	)

	_, _ = fmt.Fprintln(w, info+info2)
}

Ejemplo de devolución
Insertar descripción de la imagen aquí

Código

mdb.go

/*
Package study_package
*/
package study_package

import (
	"database/sql"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"time"
)

// 全局 db 对象
var DB *sql.DB

// ConnectionPool 连接池的学习
func ConnectionPool() {
    
    
	fmt.Println("mysql 连接池实践 -- ")

	// 连接 db
	db, err := sql.Open("mysql", "root:12345678@/spider?charset=utf8")
	if err != nil {
    
    
		panic(err)
	}
	//defer db.Close()
	db.SetMaxOpenConns(100)                    //  设置连接数总数
	db.SetMaxIdleConns(50)                     //  设置最大空闲连接数, 该数值应该小于等于 SetMaxOpenConns 设置的值
	db.SetConnMaxLifetime(0)                   // 设置连接最大生命周期, 默认为 0(不限制), 我不建议设置该值, 只有当 mysql 服务器出现问题, 会导致连接报错, 恢复后可以自动恢复正常, 而我们配置了时间也不能卡住出问题的时间, 配置小还不如使用 SetConnMaxIdleTime 来解决
	db.SetConnMaxIdleTime(86400 * time.Second) // 设置空闲状态最大生命周期, 该值应小于 mysql.wait_timeout 的值, 以避免被服务端断开连接, 产生报错影响业务。

	// 创建连接池
	DB = db
}

web.go

// Copyright 2023 The wangkai. ALL rights reserved.

package study_package

import (
	"fmt"
	"net/http"
)


// Pool 学习搭建 数据库连接池相关概念
func Pool(w http.ResponseWriter, r *http.Request) {
    
    
	var count int
	// 对应数据库查询
	row := DB.QueryRow("SELECT COUNT(1) count FROM `xz_house`")
	//  遍历数据
	err := row.Scan(&count)
	if err != nil {
    
    
		fmt.Println(err)
	}

	_, _ = fmt.Fprintln(w, count)
}

// getDbStats 获取 DB 状态和指标
func getDbStats(w http.ResponseWriter, r *http.Request) {
    
    
	info := fmt.Sprintf("最大连接数:%d,  当前总连接数;%d,  已使用: %d, 空闲数量:%d \n", DB.Stats().MaxOpenConnections, DB.Stats().OpenConnections, DB.Stats().InUse, DB.Stats().Idle)
	info2 := fmt.Sprintf("数量指标 :) \n等待连接数量;%d,  等待创建新连接时长(秒): %f, 空闲超限关闭数量:%d, 空闲超时关闭数量:%d, 连接超时关闭数量:%d \n",
		DB.Stats().WaitCount,
		DB.Stats().WaitDuration.Seconds(),
		DB.Stats().MaxIdleClosed,
		DB.Stats().MaxIdleTimeClosed,
		DB.Stats().MaxLifetimeClosed,
	)

	_, _ = fmt.Fprintln(w, info+info2)
}

web_test.go

package study_package

import (
	"net/http"
	"testing"
)

func TestPool(t *testing.T) {
    
    
	type args struct {
    
    
		w http.ResponseWriter
		r *http.Request
	}
	tests := []struct {
    
    
		name string
		args args
	}{
    
    
		{
    
    "base", args{
    
    
			w: nil,
			r: nil,
		}},
	}
	for _, tt := range tests {
    
    
		t.Run(tt.name, func(t *testing.T) {
    
    
			// 创建连接池
			ConnectionPool()
			http.HandleFunc("/pool", Pool)
			http.HandleFunc("/getDbStats", getDbStats)
			// 创建 Listen Socket, 监听 9090 端口
			err := http.ListenAndServe(":9090", nil)
			if err == nil {
    
    
				log.Fatal(" ListenAndServe:", err)
			}
		})
	}
}

Resumir

Solo si domina la configuración de parámetros relacionados con las funciones de Go y comprende la configuración de mysql, podrá volverse más competente en el uso de la función del grupo de conexiones de Go, garantizando así la solidez del servicio.

Por supuesto, no podemos centrarnos solo en el nivel del código, también debemos comprender los indicadores del hardware, como la memoria, la lectura y escritura de E/S, la CPU, etc. Sin embargo, en ese momento, existía la operación y el mantenimiento profesionales. intervenir en apoyo Después de todo, nuestros negocios diarios y asuntos personales, como Todo lo mencionado en el prefacio, se puede resolver adecuadamente.

Supongo que te gusta

Origin blog.csdn.net/weixin_43832080/article/details/128901991
Recomendado
Clasificación