面试题答案
一键面试优化思路
- 合理设置context超时时间:
- 在高并发场景下,过长的超时时间可能导致连接长时间占用,影响系统整体并发能力;而过短的超时时间可能导致请求频繁失败。需要根据业务场景和数据库处理能力来精确设置。例如,对于简单的查询操作,可以设置相对较短的超时时间。
- 复用context:
- 在可能的情况下,尽量复用已有的context,避免频繁创建新的context。例如,在一个服务模块中,如果多个数据库操作逻辑是相关联的,可以使用同一个context,减少创建和销毁context的开销。
- 结合数据库连接池:
- 连接池参数优化:合理配置连接池的最大连接数、最小连接数、连接的最大存活时间等参数。在高并发环境下,如果最大连接数设置过小,可能导致请求等待连接资源;设置过大则可能耗尽系统资源。例如,可以根据服务器的硬件资源(如CPU、内存等)和预估的并发请求量来动态调整这些参数。
- 连接池预初始化:在系统启动时,预先初始化一定数量的连接到连接池中,避免在高并发请求到来时才创建连接导致的性能抖动。
代码示例(以Go语言为例)
- 使用context结合数据库连接池:
package main
import (
"context"
"database/sql"
"fmt"
"time"
_ "github.com/go - sql - driver/mysql"
)
func main() {
// 初始化数据库连接池
db, err := sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/test?parseTime=true")
if err!= nil {
panic(err.Error())
}
defer db.Close()
// 设置连接池参数
db.SetMaxIdleConns(10)
db.SetMaxOpenConns(100)
db.SetConnMaxLifetime(time.Minute * 5)
// 创建context
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
var result string
err = db.QueryRowContext(ctx, "SELECT 'Hello, World!'").Scan(&result)
if err!= nil {
fmt.Println("Query error:", err)
return
}
fmt.Println(result)
}
在上述代码中:
- 首先初始化了一个MySQL数据库连接池,并设置了连接池的相关参数。
- 然后创建了一个带有超时时间的context,在执行数据库查询操作时,使用
QueryRowContext
方法传入该context,这样如果查询操作超过设定的5秒超时时间,会自动取消操作,避免连接长时间占用。
- 复用context示例:
package main
import (
"context"
"database/sql"
"fmt"
"time"
_ "github.com/go - sql - driver/mysql"
)
func performQueries(ctx context.Context, db *sql.DB) {
var result1 string
err := db.QueryRowContext(ctx, "SELECT 'Result 1'").Scan(&result1)
if err!= nil {
fmt.Println("Query 1 error:", err)
return
}
fmt.Println(result1)
var result2 string
err = db.QueryRowContext(ctx, "SELECT 'Result 2'").Scan(&result2)
if err!= nil {
fmt.Println("Query 2 error:", err)
return
}
fmt.Println(result2)
}
func main() {
db, err := sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/test?parseTime=true")
if err!= nil {
panic(err.Error())
}
defer db.Close()
db.SetMaxIdleConns(10)
db.SetMaxOpenConns(100)
db.SetConnMaxLifetime(time.Minute * 5)
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
performQueries(ctx, db)
}
在这个示例中,performQueries
函数中复用了传入的context进行多个数据库查询操作,减少了context创建和销毁的开销。