go语言高并发数据库查询 go mysql 并发 用什么库

为什么要使用 Go 语言?Go 语言的优势在哪里?

1、简单易学。

创新互联建站是专业的应县网站建设公司,应县接单;提供成都网站设计、成都做网站,网页设计,网站设计,建网站,PHP网站建设等专业做网站服务;采用PHP框架,可快速的进行应县网站开发网页制作和功能扩展;专业做搜索引擎喜爱的网站,专业的做网站团队,希望更多企业前来合作!

Go语言的作者本身就很懂C语言,所以同样Go语言也会有C语言的基因,所以对于程序员来说,Go语言天生就会让人很熟悉,容易上手。

2、并发性好。

Go语言天生支持并发,可以充分利用多核,轻松地使用并发。 这是Go语言最大的特点。

描述

Go的语法接近C语言,但对于变量的声明有所不同。Go支持垃圾回收功能。Go的并行模型是以东尼·霍尔的通信顺序进程(CSP)为基础,采取类似模型的其他语言包括Occam和Limbo,但它也具有Pi运算的特征,比如通道传输。

在1.8版本中开放插件(Plugin)的支持,这意味着现在能从Go中动态加载部分函数。

与C++相比,Go并不包括如枚举、异常处理、继承、泛型、断言、虚函数等功能,但增加了 切片(Slice) 型、并发、管道、垃圾回收、接口(Interface)等特性的语言级支持。

GO语言商业案例(十八):stream

切换到新语言始终是一大步,尤其是当您的团队成员只有一个时有该语言的先前经验。现在,Stream 的主要编程语言从 Python 切换到了 Go。这篇文章将解释stream决定放弃 Python 并转向 Go 的一些原因。

Go 非常快。性能类似于 Java 或 C++。对于用例,Go 通常比 Python 快 40 倍。

对于许多应用程序来说,编程语言只是应用程序和数据库之间的粘合剂。语言本身的性能通常并不重要。然而,Stream 是一个API 提供商,为 700 家公司和超过 5 亿最终用户提供提要和聊天平台。多年来,我们一直在优化 Cassandra、PostgreSQL、Redis 等,但最终,您会达到所使用语言的极限。Python 是一门很棒的语言,但对于序列化/反序列化、排名和聚合等用例,它的性能相当缓慢。我们经常遇到性能问题,Cassandra 需要 1 毫秒来检索数据,而 Python 会花费接下来的 10 毫秒将其转换为对象。

看看我如何开始 Go 教程中的一小段 Go 代码。(这是一个很棒的教程,也是学习 Go 的一个很好的起点。)

如果您是 Go 新手,那么在阅读那个小代码片段时不会有太多让您感到惊讶的事情。它展示了多个赋值、数据结构、指针、格式和一个内置的 HTTP 库。当我第一次开始编程时,我一直喜欢使用 Python 更高级的功能。Python 允许您在编写代码时获得相当的创意。例如,您可以:

这些功能玩起来很有趣,但是,正如大多数程序员会同意的那样,在阅读别人的作品时,它们通常会使代码更难理解。Go 迫使你坚持基础。这使得阅读任何人的代码并立即了解发生了什么变得非常容易。 注意:当然,它实际上有多“容易”取决于您的用例。如果你想创建一个基本的 CRUD API,我仍然推荐 Django + DRF或 Rails。

作为一门语言,Go 试图让事情变得简单。它没有引入许多新概念。重点是创建一种非常快速且易于使用的简单语言。它唯一具有创新性的领域是 goroutine 和通道。(100% 正确CSP的概念始于 1977 年,所以这项创新更多是对旧思想的一种新方法。)Goroutines 是 Go 的轻量级线程方法,通道是 goroutines 之间通信的首选方式。Goroutines 的创建非常便宜,并且只需要几 KB 的额外内存。因为 Goroutine 非常轻量,所以有可能同时运行数百甚至数千个。您可以使用通道在 goroutine 之间进行通信。Go 运行时处理所有复杂性。goroutines 和基于通道的并发方法使得使用所有可用的 CPU 内核和处理并发 IO 变得非常容易——所有这些都不会使开发复杂化。与 Python/Java 相比,在 goroutine 上运行函数需要最少的样板代码。您只需在函数调用前加上关键字“go”:

Go 的并发方法很容易使用。与 Node 相比,这是一种有趣的方法,开发人员必须密切关注异步代码的处理方式。Go 中并发的另一个重要方面是竞争检测器。这样可以很容易地确定异步代码中是否存在任何竞争条件。

我们目前用 Go 编写的最大的微服务编译需要 4 秒。与以编译速度慢而闻名的 Java 和 C++ 等语言相比,Go 的快速编译时间是一项重大的生产力胜利。我喜欢在程序编译的时候摸鱼,但在我还记得代码应该做什么的同时完成事情会更好。

首先,让我们从显而易见的开始:与 C++ 和 Java 等旧语言相比,Go 开发人员的数量并不多。根据StackOverflow的数据, 38% 的开发人员知道 Java, 19.3% 的人知道 C++,只有 4.6% 的人知道 Go。GitHub 数据显示了类似的趋势:Go 比 Erlang、Scala 和 Elixir 等语言使用更广泛,但不如 Java 和 C++ 流行。幸运的是,Go 是一种非常简单易学的语言。它提供了您需要的基本功能,仅此而已。它引入的新概念是“延迟”声明和内置的并发管理与“goroutines”和通道。(对于纯粹主义者来说:Go 并不是第一种实现这些概念的语言,只是第一种使它们流行起来的语言。)任何加入团队的 Python、Elixir、C++、Scala 或 Java 开发人员都可以在一个月内在 Go 上发挥作用,因为它的简单性。与许多其他语言相比,我们发现组建 Go 开发人员团队更容易。如果您在博尔德和阿姆斯特丹等竞争激烈的生态系统中招聘人员,这是一项重要的优势。

对于我们这样规模的团队(约 20 人)来说,生态系统很重要。如果您必须重新发明每一个小功能,您根本无法为您的客户创造价值。Go 对我们使用的工具有很好的支持。实体库已经可用于 Redis、RabbitMQ、PostgreSQL、模板解析、任务调度、表达式解析和 RocksDB。与 Rust 或 Elixir 等其他较新的语言相比,Go 的生态系统是一个重大胜利。它当然不如 Java、Python 或 Node 之类的语言好,但它很可靠,而且对于许多基本需求,你会发现已经有高质量的包可用。

Gofmt 是一个很棒的命令行实用程序,内置在 Go 编译器中,用于格式化代码。就功能而言,它与 Python 的 autopep8 非常相似。我们大多数人并不真正喜欢争论制表符与空格。格式的一致性很重要,但实际的格式标准并不那么重要。Gofmt 通过使用一种正式的方式来格式化您的代码来避免所有这些讨论。

Go 对协议缓冲区和 gRPC 具有一流的支持。这两个工具非常适合构建需要通过 RPC 通信的微服务。您只需要编写一个清单,在其中定义可以进行的 RPC 调用以及它们采用的参数。然后从这个清单中自动生成服务器和客户端代码。生成的代码既快速又具有非常小的网络占用空间并且易于使用。从同一个清单中,您甚至可以为许多不同的语言生成客户端代码,例如 C++、Java、Python 和 Ruby。因此,内部流量不再有模棱两可的 REST 端点,您每次都必须编写几乎相同的客户端和服务器代码。.

Go 没有像 Rails 用于 Ruby、Django 用于 Python 或 Laravel 用于 PHP 那样的单一主导框架。这是 Go 社区内激烈争论的话题,因为许多人主张你不应该一开始就使用框架。我完全同意这对于某些用例是正确的。但是,如果有人想构建一个简单的 CRUD API,他们将更容易使用 Django/DJRF、Rails Laravel 或Phoenix。对于 Stream 的用例,我们更喜欢不使用框架。然而,对于许多希望提供简单 CRUD API 的新项目来说,缺乏主导框架将是一个严重的劣势。

Go 通过简单地从函数返回错误并期望调用代码来处理错误(或将其返回到调用堆栈)来处理错误。虽然这种方法有效,但很容易失去问题的范围,以确保您可以向用户提供有意义的错误。错误包通过允许您向错误添加上下文和堆栈跟踪来解决此问题。另一个问题是很容易忘记处理错误。像 errcheck 和 megacheck 这样的静态分析工具可以方便地避免犯这些错误。虽然这些变通办法效果很好,但感觉不太对劲。您希望该语言支持正确的错误处理。

Go 的包管理绝不是完美的。默认情况下,它无法指定特定版本的依赖项,也无法创建可重现的构建。Python、Node 和 Ruby 都有更好的包管理系统。但是,使用正确的工具,Go 的包管理工作得很好。您可以使用Dep来管理您的依赖项,以允许指定和固定版本。除此之外,我们还贡献了一个名为的开源工具VirtualGo,它可以更轻松地处理用 Go 编写的多个项目。

我们进行的一个有趣的实验是在 Python 中使用我们的排名提要功能并在 Go 中重写它。看看这个排名方法的例子:

Python 和 Go 代码都需要执行以下操作来支持这种排名方法:

开发 Python 版本的排名代码大约花了 3 天时间。这包括编写代码、单元测试和文档。接下来,我们花了大约 2 周的时间优化代码。其中一项优化是将分数表达式 (simple_gauss(time)*popularity) 转换为抽象语法树. 我们还实现了缓存逻辑,可以在未来的特定时间预先计算分数。相比之下,开发此代码的 Go 版本大约需要 4 天时间。性能不需要任何进一步的优化。因此,虽然 Python 的最初开发速度更快,但基于 Go 的版本最终需要我们团队的工作量大大减少。另外一个好处是,Go 代码的执行速度比我们高度优化的 Python 代码快大约 40 倍。现在,这只是我们通过切换到 Go 体验到的性能提升的一个示例。

与 Python 相比,我们系统的其他一些组件在 Go 中构建所需的时间要多得多。作为一个总体趋势,我们看到 开发 Go 代码需要更多的努力。但是,我们花更少的时间 优化 代码以提高性能。

我们评估的另一种语言是Elixir.。Elixir 建立在 Erlang 虚拟机之上。这是一种迷人的语言,我们之所以考虑它,是因为我们的一名团队成员在 Erlang 方面拥有丰富的经验。对于我们的用例,我们注意到 Go 的原始性能要好得多。Go 和 Elixir 都可以很好地服务数千个并发请求。但是,如果您查看单个请求的性能,Go 对于我们的用例来说要快得多。我们选择 Go 而不是 Elixir 的另一个原因是生态系统。对于我们需要的组件,Go 有更成熟的库,而在许多情况下,Elixir 库还没有准备好用于生产环境。培训/寻找开发人员使用 Elixir 也更加困难。这些原因使天平向 Go 倾斜。Elixir 的 Phoenix 框架看起来很棒,绝对值得一看。

Go 是一种非常高性能的语言,对并发有很好的支持。它几乎与 C++ 和 Java 等语言一样快。虽然与 Python 或 Ruby 相比,使用 Go 构建东西确实需要更多时间,但您将节省大量用于优化代码的时间。我们在Stream有一个小型开发团队,为超过 5 亿最终用户提供动力和聊天。Go 结合了 强大的生态系统 、新开发人员的 轻松入门、快速的性能 、对并发的 可靠支持和高效的编程环境 ,使其成为一个不错的选择。Stream 仍然在我们的仪表板、站点和机器学习中利用 Python 来提供个性化的订阅源. 我们不会很快与 Python 说再见,但今后所有性能密集型代码都将使用 Go 编写。我们新的聊天 API也完全用 Go 编写。

国内重要的 Go 语言项目:TiDB 3.0 GA,稳定性和性能大幅提升

TiDB 是 PingCAP 自主研发的开源分布式关系型数据库,具备商业级数据库的数据可靠性,可用性,安全性等特性,支持在线弹性水平扩展,兼容 MySQL 协议及生态,创新性实现 OLTP 及 OLAP 融合。

TiDB 3.0 版本显著提升了大规模集群的稳定性,集群支持 150+ 存储节点,300+TB 存储容量长期稳定运行。易用性方面引入大量降低用户运维成本的优化,包括引入 Information_Schema 中的多个实用系统视图、EXPLAIN ANALYZE、SQL Trace 等。在性能方面,特别是 OLTP 性能方面,3.0 比 2.1 也有大幅提升,其中 TPC-C 性能提升约 4.5 倍,Sysbench 性能提升约 1.5 倍,OLAP 方面,TPC-H 50G Q15 因实现 View 可以执行,至此 TPC-H 22 个 Query 均可正常运行。新功能方面增加了窗口函数、视图(实验特性)、分区表、插件系统、悲观锁(实验特性)。

截止本文发稿时 TiDB 已在 500+ 用户的生产环境中长期稳定运行,涵盖金融、保险、制造,互联网, 游戏 等领域,涉及交易、数据中台、 历史 库等多个业务场景。不同业务场景对关系型数据库的诉求可用 “百花齐放”来形容,但对关系数据库最根本的诉求未发生任何变化,如数据可靠性,系统稳定性,可扩展性,安全性,易用性等。请跟随我们的脚步梳理 TiDB 3.0 有什么样的惊喜。

3.0 与 2.1 版本相比,显著提升了大规模集群的稳定性,支持单集群 150+ 存储节点,300+TB 存储容量长期稳定运行,主要的优化点如下:

1. 优化 Raft 副本之间的心跳机制,按照 Region 的活跃程度调整心跳频率,减小冷数据对集群的负担。

2. 热点调度策略支持更多参数配置,采用更高优先级,并提升热点调度的准确性。

3. 优化 PD 调度流程,提供调度限流机制,提升系统稳定性。

4. 新增分布式 GC 功能,提升 GC 的性能,降低大集群 GC 时间,提升系统稳定性。

众所周知,数据库查询计划的稳定性对业务至关重要,TiDB 3.0 版本采用多种优化手段提升查询计划的稳定性,如下:

1. 新增 Fast Analyze 功能,提升收集统计信息的速度,降低集群资源的消耗及对业务的影响。

2. 新增 Incremental Analyze 功能,提升收集单调递增的索引统计信息的速度,降低集群资源的消耗及对业务的影响。

3. 在 CM-Sketch 中新增 TopN 的统计信息,缓解 CM-Sketch 哈希冲突导致估算偏大,提升代价估算的准确性,提升查询计划的稳定性。

4. 引入 Skyline Pruning 框架,利用规则防止查询计划过度依赖统计信息,缓解因统计信息滞后导致选择的查询计划不是最优的情况,提升查询计划的稳定性。

5. 新增 SQL Plan Management 功能,支持在查询计划不准确时手动绑定查询计划,提升查询计划的稳定性。

1. OLTP

3.0 与 2.1 版本相比 Sysbench 的 Point Select,Update Index,Update Non-Index 均提升约 1.5 倍,TPC-C 性能提升约 4.5 倍。主要的优化点如下:

1. TiDB 持续优化 SQL 执行器,包括:优化 NOT EXISTS 子查询转化为 Anti Semi Join,优化多表 Join 时 Join 顺序选择等。

2. 优化 Index Join 逻辑,扩大 Index Join 算子的适用场景并提升代价估算的准确性。

3. TiKV 批量接收和发送消息功能,提升写入密集的场景的 TPS 约 7%,读密集的场景提升约 30%。

4. TiKV 优化内存管理,减少 Iterator Key Bound Option 的内存分配和拷贝,多个 Column Families 共享 block cache 提升 cache 命中率等手段大幅提升性能。

5. 引入 Titan 存储引擎插件,提升 Value 值超过 1KB 时性能,缓解 RocksDB 写放大问题,减少磁盘 IO 的占用。

6. TiKV 新增多线程 Raftstore 和 Apply 功能,提升单节点内可扩展性,进而提升单节点内并发处理能力和资源利用率,降低延时,大幅提升集群写入能力。

TiDB Lightning 性能与 2019 年年初相比提升 3 倍,从 100GB/h 提升到 300GB/h,即 28MB/s 提升到 85MB/s,优化点,如下:

1. 提升 SQL 转化成 KV Pairs 的性能,减少不必要的开销。

2. 提升单表导入性能,单表支持批量导入。

3. 提升 TiKV-Importer 导入数据性能,支持将数据和索引分别导入。

4. TiKV-Importer 支持上传 SST 文件限速功能。

RBAC(Role-Based Access Control,基于角色的权限访问控制) 是商业系统中最常见的权限管理技术之一,通过 RBAC 思想可以构建最简单“用户-角色-权限”的访问权限控制模型。RBAC 中用户与角色关联,权限与角色关联,角色与权限之间一般是多对多的关系,用户通过成为什么样的角色获取该角色所拥有的权限,达到简化权限管理的目的,通过此版本的迭代 RBAC 功能开发完成。

IP 白名单功能(企业版特性) :TiDB 提供基于 IP 白名单实现网络安全访问控制,用户可根据实际情况配置相关的访问策略。

Audit log 功能(企业版特性) :Audit log 记录用户对数据库所执行的操作,通过记录 Audit log 用户可以对数据库进行故障分析,行为分析,安全审计等,帮助用户获取数据执行情况。

加密存储(企业版特性) :TiDB 利用 RocksDB 自身加密功能,实现加密存储的功能,保证所有写入到磁盘的数据都经过加密,降低数据泄露的风险。

完善权限语句的权限检查 ,新增 ANALYZE,USE,SET GLOBAL,SHOW PROCESSLIST 语句权限检查。

1. 新增 SQL 方式查询慢查询,丰富 TiDB 慢查询日志内容,如:Coprocessor 任务数,平均/最长/90% 执行/等待时间,执行/等待时间最长的 TiKV 地址,简化慢查询定位工作,提高排查慢查询问题效率,提升产品易用性。

2. 新增系统配置项合法性检查,优化系统监控项等,提升产品易用性。

3. 新增对 TableReader、IndexReader 和 IndexLookupReader 算子内存使用情况统计信息,提高 Query 内存使用统计的准确性,提升处理内存消耗较大语句的效率。

4. 制定日志规范,重构日志系统,统一日志格式,方便用户理解日志内容,有助于通过工具对日志进行定量分析。

5. 新增 EXPLAIN ANALYZE 功能,提升SQL 调优的易用性。

6. 新增 SQL 语句 Trace 功能,方便排查问题。

7. 新增通过 unix_socket 方式连接数据库。

8. 新增快速恢复被删除表功能,当误删除数据时可通过此功能快速恢复数据。

TiDB 3.0 新增 TiFlash 组件,解决复杂分析及 HTAP 场景。TiFlash 是列式存储系统,与行存储系统实时同步,具备低延时,高性能,事务一致性读等特性。 通过 Raft 协议从 TiKV 中实时同步行存数据并转化成列存储格式持久化到一组独立的节点,解决行列混合存储以及资源隔离性问题。TiFlash 可用作行存储系统(TiKV)实时镜像,实时镜像可独立于行存储系统,将行存储及列存储从物理隔离开,提供完善的资源隔离方案,HTAP 场景最优推荐方案;亦可用作行存储表的索引,配合行存储对外提供智能的 OLAP 服务,提升约 10 倍复杂的混合查询的性能。

TiFlash 目前处于 Beta 阶段,计划 2019 年 12 月 31 日之前 GA,欢迎大家申请试用。

未来我们会继续投入到系统稳定性,易用性,性能,弹性扩展方面,向用户提供极致的弹性伸缩能力,极致的性能体验,极致的用户体验。

稳定性方面 V4.0 版本将继续完善 V3.0 未 GA 的重大特性,例如:悲观事务模型,View,Table Partition,Titan 行存储引擎,TiFlash 列存储引擎;引入近似物理备份恢复解决分布数据库备份恢复难题;优化 PD 调度功能等。

性能方面 V4.0 版本将继续优化事务处理流程,减少事务资源消耗,提升性能,例如:1PC,省去获取 commit ts 操作等。

弹性扩展方面,PD 将提供弹性扩展所需的元信息供外部系统调用,外部系统可根据元信息及负载情况动态伸缩集群规模,达成节省成本的目标。

我们相信战胜“未知”最好的武器就是社区的力量,基础软件需要坚定地走开源路线。截止发稿我们已经完成 41 篇源码阅读文章。TiDB 开源社区总计 265 位 Contributor,6 位 Committer,在这里我们对社区贡献者表示由衷的感谢,希望更多志同道合的人能加入进来,也希望大家在 TiDB 这个开源社区能够有所收获。

TiDB 3.0 GA Release Notes:

golang配制高性能sql.DB

有很多教程是关于Go的sql.DB类型和如何使用它来执行SQL数据库查询的。但大多数内容都没有讲述 SetMaxOpenConns() , SetMaxIdleConns() 和 SetConnMaxLifetime()方法, 您可以使用它们来配置sql.DB的行为并改变其性能。

转自:

整理:go语言中文文档:

在本文我将详细解释这些设置的作用,并说明它们所能产生的(积极和消极)影响。

一个sql.DB对象就是一个数据库连接池,它包含“正在用”和“空闲的”连接。一个正在用的连接指的是,你正用它来执行数据库任务,例如执行SQL语句或行查询。当任务完成连接就是空闲的。

当您创建sql.DB执行数据库任务时,它将首先检查连接池中是否有可用的空闲连接。如果有可用的连接,那么Go将重用现有连接,并在执行任务期间将其标记为正在使用。如果池中没有空闲连接,而您需要一个空闲连接,那么Go将创建一个新的连接。

默认情况下,在同一时间打开连接的数量是没有限制(包含使用中+空闲)。但你可以通过SetMaxOpenConns()方法实现自定义限制,如下所示:

在这个示例代码中,连接池现在有5个并发打开的连接数。如果所有5个连接都已经被标记为正在使用,并且需要另一个新的连接,那么应用程序将被迫等待,直到5个连接中的一个被释放并变为空闲。

为了说明更改MaxOpenConns的影响,我运行了一个基准测试,将最大打开连接数设置为1、2、5、10和无限。基准测试在PostgreSQL数据库上执行并行的INSERT语句,您可以在这里找到代码。测试结果:

对于这个基准测试,我们可以看到,允许打开的连接越多,在数据库上执行INSERT操作所花费的时间就越少(打开的连接数为1时,执行速度3129633ns/op,而无限连接:531030ns/op——大约快了6倍)。这是因为允许打开的连接越多,可以并发执行的数据库查询就越多。

默认情况下,sql.DB允许连接池中最多保留2个空闲连接。你可以通过SetMaxIdleConns()方法改变它,如下所示:

从理论上讲,允许池中有更多的空闲连接将提高性能,因为这样就不太可能从头开始建立新连接——因此有助于提升数据库性能。

让我们来看看相同的基准测试,最大空闲连接设置为none, 1,2,5和10:

当MaxIdleConns设置为none时,必须为每个INSERT从头创建一个新的连接,我们可以从基准测试中看到,平均运行时和内存使用量相对较高。

只允许保留和重用一个空闲连接对基准测试影响特别明显——它将平均运行时间减少了大约8倍,内存使用量减少了大约20倍。继续增加空闲连接池的大小会使性能变得更好,尽管改进并不明显。

那么,您应该维护一个大的空闲连接池吗?答案取决于应用程序。重要的是要意识到保持空闲连接是有代价的—它占用了可以用于应用程序和数据库的内存。

还有一种可能是,如果一个连接空闲时间太长,那么它可能会变得不可用。例如,MySQL的wait_timeout设置将自动关闭任何8小时(默认)内未使用的连接。

当发生这种情况时,sql.DB会优雅地处理它。坏连接将自动重试两次,然后放弃,此时Go将该连接从连接池中删除,并创建一个新的连接。因此,将MaxIdleConns设置得太大可能会导致连接变得不可用,与空闲连接池更小(使用更频繁的连接更少)相比,会占有更多的资源。所以,如果你很可能很快就会再次使用,你只需保持一个空闲的连接。

最后要指出的是,MaxIdleConns应该总是小于或等于MaxOpenConns。Go强制执行此操作,并在必要时自动减少MaxIdleConns。

现在让我们看看SetConnMaxLifetime()方法,它设置连接可重用的最大时间长度。如果您的SQL数据库也实现了最大连接生命周期,或者—例如—您希望方便地在负载均衡器后交换数据库,那么这将非常有用。

你可以这样使用它:

在这个例子中,所有的连接都将在创建后1小时“过期”,并且在过期后无法重用。但注意:

从理论上讲,ConnMaxLifetime越短,连接过期的频率就越高——因此,需要从头创建连接的频率就越高。为了说明这一点,我运行了将ConnMaxLifetime设置为100ms、200ms、500ms、1000ms和无限(永远重用)的基准测试,默认设置为无限打开连接和2个空闲连接。这些时间段显然比您在大多数应用程序中使用的时间要短得多,但它们有助于很好地说明行为。

在这些特定的基准测试中,我们可以看到,与无限生存期相比,在100ms生存期时内存使用量增加了3倍以上,而且每个INSERT的平均运行时也稍微长一些。

如果您在代码中设置了ConnMaxLifetime,那么一定要记住连接将过期(随后重新创建)的频率。例如,如果您总共有100个连接,而ConnMaxLifetime为1分钟,那么您的应用程序可能每秒钟杀死和重新创建1.67个连接(平均值)。您不希望这个频率太大,最终会阻碍性能,而不是提高性能。

最后,如果不说明超过数据库连接数量的硬限制将会发生什么,那么本文就不完整了。 为了说明这一点,我将修改postgresql.conf文件,这样总共只允许5个连接(默认是100个)…

然后在无限连接的情况下重新运行基准测试……

一旦达到5个连接的硬限制,数据库驱动程序(pq)立即返回一个太多客户端连接的错误消息,而无法完成INSERT。为了防止这个错误,我们需要将sql.DB中打开连接的最大总数(正在使用的+空闲的)设置为低于5。像这样:

现在,sql.DB在任何时候最多只能创建3个连接,基准测试运行时应该不会出现任何错误。但是这样做需要注意:当达到开放连接数限制,并且所有连接都在使用时,应用程序需要执行的任何新的数据库任务都将被迫等待,直到连接标记为空闲。例如,在web应用程序的上下文中,用户的HTTP请求看起来会“挂起”,甚至在等待数据库任务运行时可能会超时。

为了减轻这种情况,你应该始终在一个上下文中传递。在调用数据库时,启用上下文的方法(如ExecContext()),使用固定的、快速的超时上下文对象。

总结

1、根据经验,应该显式设置MaxOpenConns值。这应该小于数据库和基础设施对连接数量的硬性限制。

2、一般来说,更高的MaxOpenConns和MaxIdleConns值将带来更好的性能。但你应该注意到效果是递减的,连接池空闲连接太多(连接没有被重用,最终会变坏)实际上会导致性能下降。

3、为了降低上面第2点带来的风险,您可能需要设置一个相对较短的ConnMaxLifetime。但你也不希望它太短,导致连接被杀死或不必要地频繁重建。

4、MaxIdleConns应该总是小于或等于MaxOpenConns。

对于中小型web应用程序,我通常使用以下设置作为起点,然后根据实际吞吐量水平的负载测试结果进行优化。


网站栏目:go语言高并发数据库查询 go mysql 并发 用什么库
网页地址:http://azwzsj.com/article/doosiij.html