全文1416字,阅读文本大概5分钟
最近业务上大量使用clickhouse,当我们压测的时候发现,clickhouse并发写入性能支持的不是很好,这个是由于clickhouse实现并行查询机制,造成了我们对clickhouse的连接需要控制。最开始的时候我们的思路是想针对于clickhouse写一个专用的全局连接网关服务,后面发现实现这个全局连接网关需要处理其他服务和这个连接网关服务之间的各种连接状态,各种连接异常情况,发现实现起来问题会比较多,而且这个开发的时间是比较长的。后面我们深入研究了一下sqlx.DB,当然sql.DB也是可以连接clickhouse的,但是他没有select和get的方法,用起来是比较麻烦。最后我们决定用sqlx.DB,深入研究一下sqlx.DB,sqlx.DB不是一个连接,这个而是一个连接池,它可以通过sqlx.Open来创建一个对接对象。
SetMaxOpenConns 方法
默认情况下,同时打开的连接数 (使用中 + 空闲) 没有限制。但是您可以通过 SetMaxOpenConns 方法实现对连接数的限制,如下所示:
//初始化一个新的连接池
db, err := sqlx.Open("clickhouse", "tcp://127.0.0.1:9000")
if err != nil {
log.Fatal(err)
}
//设置同时打开的连接数(使用中+空闲)
//设为5。将此值设置为小于或等于0表示没有限制
//最大限制(这也是默认设置)。
db.SetMaxOpenConns(5)
在此示例代码中,连接池现在最大限制为 5 个并发打开的连接。如果 5 个连接全部都已标记为使用中,并且需要另一个新连接,则应用程序将被迫等待,直到 5 个连接的其中一个被释放并变为空闲状态
SetMaxIdleConns 方法
默认情况下 sql.DB 会在链接池中最多保留 2 个空闲链接。可以通过 SetMaxIdleConns() 方法更改此方法,如下所示:
// 初始化一个新的链接池
db, err := sqlx.Open("clickhouse", "tcp://127.0.0.1:9000")
if err != nil {
log.Fatal(err)
}
// 将最大并发空闲链接数设置为 5.
// 小于或等于 0 表示不保留任何空闲链接.
db.SetMaxIdleConns(5)
理论上来说,在链接池中允许更多数量的空闲链接将提高性能,因为它使从头开始建立新链接的可能性降低了,因此有助于节省资源。
SetConnMaxLifetime 方法
现在让我们看一下 SetConnMaxLifetime() 方法,该方法设置了可重用链接的最大时间长度。如果你得 SQL 数据还实现了最大链接得生命周期,或者如果你希望方便得再负载均衡器之后轻松得交换数据库得话这将非常有用.
您可以这样使用它:
//初始化一个新的连接池
db, err := sqlx.Open("clickhouse", "tcp://127.0.0.1:9000")
if err != nil {
log.Fatal(err)
}
// 设置最大生存时间为1小时
// 设置为0,表示没有最大生存期,并且连接会被重用
// forever (这是默认配置).
db.SetConnMaxLifetime(time.Hour)
在此示例中,我们所有的连接将在首次创建后一个小时 "过期",并且过期后无法重用。但请注意:
这不能保证连接将在连接池中存在一个小时;连接很有可能由于某种原因而变得无法使用,并在此之前被自动关闭。
建立连接后仍可以使用超过一小时 - 在那之后它就无法 启动 重用。
这不是空闲超时。连接将在第一次创建后 1 个小时到期,而不是在上一次空闲后 1 个小时到期。
每秒自动执行一次清除操作,从连接池中删除 “过期” 的连接。
理论上, ConnMaxLifetime 越短,连接过期的次数就会越频繁 — 因此 — 需要从头开始创建连接的次数也就越多。
总结:关于开头我们说了连接数问题,最后我们通过控制每个服务的最大连接数来解决这个clickhouse的并发问题。
参考文档:
https://www.alexedwards.net/blog/configuring-sqldb
http://jmoiron.github.io/sqlx/