网站首页 > 文章中心 > 其它

go语言数据池

作者:小编 更新时间:2023-10-14 19:01:47 浏览量:7人看过

golang sync.pool对象复用 并发原理 缓存池

在go http每一次go serve(l)都会构建Request数据结构.在大量数据请求或高并发的场景中,频繁创建销毁对象,会导致GC压力.解决办法之一就是使用对象复用技术.在http协议层之下,使用对象复用技术创建Request数据结构.在http协议层之上,可以使用对象复用技术创建(w,*r,ctx)数据结构.这样即可以回快TCP层读包之后的解析速度,也可也加快请求处理的速度.

go语言数据池-图1

先上一个测试:

结论是这样的:

貌似使用池化,性能弱爆了?这似乎与net/http使用sync.pool池化Request来优化性能的选择相违背.这同时也说明了一个问题,好的东西,如果滥用反而造成了性能成倍的下降.在看过pool原理之后,结合实例,将给出正确的使用方法,并给出预期的效果.

sync.Pool是一个 协程安全 的 临时对象池 .数据结构如下:

local 成员的真实类型是一个 poolLocal 数组,localSize 是数组长度.这涉及到Pool实现,pool为每个P分配了一个对象,P数量设置为runtime.GOMAXPROCS(0).在并发读写时,goroutine绑定的P有对象,先用自己的,没有去偷其它P的.go语言将数据分散在了各个真正运行的P中,降低了锁竞争,提高了并发能力.

不要习惯性地误认为New是一个关键字,这里的New是Pool的一个字段,也是一个闭包名称.其API:

如果不指定New字段,对象池为空时会返回nil,而不是一个新构建的对象.Get()到的对象是随机的.

原生sync.Pool的问题是,Pool中的对象会被GC清理掉,这使得sync.Pool只适合做简单地对象池,不适合作连接池.

pool创建时不能指定大小,没有数量限制.pool中对象会被GC清掉,只存在于两次GC之间.实现是pool的init方法注册了一个poolCleanup()函数,这个方法在GC之前执行,清空pool中的所有缓存对象.

注意到pool中的对象是无差异性的,加锁或者分段加锁都不是较好的做法.go的做法是为每一个绑定协程的P都分配一个子池.每个子池又分为私有池和共享列表.共享列表是分别存放在各个P之上的共享区域,而不是各个P共享的一块内存.协程拿自己P里的子池对象不需要加锁,拿共享列表中的就需要加锁了.

Get对象过程:

Put过程:

go语言数据池-图2

如何解决Get最坏情况遍历所有P才获取得对象呢:

执行结果:

单线程情况下,遍历其它无元素的P,长时间加锁性能低下.启用协程改善.

结果:

测试场景在goroutines远大于GOMAXPROCS情况下,与非池化性能差异巨大.

测试结果

可以看到同样使用*sync.pool,较大池大小的命中率较高,性能远高于空池.

池pool和缓存cache的区别.池的意思是,池内对象是可以互换的,不关心具体值,甚至不需要区分是新建的还是从池中拿出的.缓存指的是KV映射,缓存里的值互不相同,清除机制更为复杂.缓存清除算法如LRU、LIRS缓存算法.

池空间回收的几种方式.一些是GC前回收,一些是基于时钟或弱引用回收.最终确定在GC时回收Pool内对象,即不回避GC.用java的GC解释弱引用.GC的四种引用:强引用、弱引用、软引用、虚引用.虚引用即没有引用,弱引用GC但有空间则保留,软引用GC即清除.ThreadLocal的值为弱引用的例子.

regexp 包为了保证并发时使用同一个正则,而维护了一组状态机.

fmt包做字串拼接,从sync.pool拿[]byte对象.避免频繁构建再GC效率高很多.

GO语言(三十):访问关系型数据库(上)

本教程介绍了使用 Godatabase/sql及其标准库中的包访问关系数据库的基础知识.

您将使用的database/sql包包括用于连接数据库、执行事务、取消正在进行的操作等的类型和函数.

在本教程中,您将创建一个数据库,然后编写代码来访问该数据库.您的示例项目将是有关老式爵士乐唱片的数据存储库.

go语言数据池-图3

首先,为您要编写的代码创建一个文件夹.

①.、打开命令提示符并切换到您的主目录.

在 Linux 或 Mac 上:

在 Windows 上:

运行go mod init命令,为其提供新代码的模块路径.

此命令创建一个 go.mod 文件,您添加的依赖项将在其中列出以供跟踪.

注意: 在实际开发中,您会指定一个更符合您自己需求的模块路径.有关更多信息,请参阅一下文章.

GO语言(二十五):管理依赖项(上)

GO语言(二十六):管理依赖项(中)

GO语言(二十七):管理依赖项(下)

此时此刻呢,您将创建一个数据库.

在此步骤中,您将创建要使用的数据库.您将使用 DBMS 本身的 CLI 创建数据库和表,以及添加数据.

您将创建一个数据库,其中包含有关黑胶唱片上的老式爵士乐录音的数据.

这里的代码使用MySQL CLI,但大多数 DBMS 都有自己的 CLI,具有类似的功能.

①.、打开一个新的命令提示符.

在命令行,登录到您的 DBMS,如下面的 MySQL 示例所示.

将以下 SQL 代码粘贴到文件中,然后保存文件.

在此 SQL 代码中:

(1)删除名为album表. 首先执行此命令可以让您更轻松地稍后重新运行脚本.

您将使用以下形式的source命令:

此时此刻呢,您将编写一些 Go 代码进行连接,以便进行查询.

现在你已经有了一个包含一些数据的数据库,开始你的 Go 代码.

找到并导入一个数据库驱动程序,该驱动程序会将您通过database/sql包中的函数发出的请求转换为数据库可以理解的请求.

①.、在您的浏览器中,访问SQLDrivers wiki 页面以识别您可以使用的驱动程序.

在此代码中:

(1)将您的代码添加到main包中,以便您可以独立执行它.

导入驱动程序后,您将开始编写代码以访问数据库.

现在编写一些 Go 代码,让您使用数据库句柄访问数据库.

您将使用指向结构的指针sql.DB,它表示对特定数据库的访问.

编写代码

①.、进入 main.go,在import您刚刚添加的代码下方,粘贴以下 Go 代码以创建数据库句柄.

该Config结构使代码比连接字符串更容易阅读.

为了简化代码,您调用log.Fatal结束执行并将错误打印到控制台.在生产代码中,您会希望以更优雅的方式处理错误.

文件的顶部现在应该如下所示:

①.、开始跟踪 MySQL 驱动程序模块作为依赖项.

使用go get 添加 github.com/go-sql-driver/mysql 模块作为您自己模块的依赖项.使用点参数表示"获取当前目录中代码的依赖项".

连接成功了!

此时此刻呢,您将查询一些数据.

go语言TCP连接池rocket049/connpool使用

安装:

可调用的函数:

调用示例:

以上就是土嘎嘎小编为大家整理的go语言数据池相关主题介绍,如果您觉得小编更新的文章只要能对粉丝们有用,就是我们最大的鼓励和动力,不要忘记讲本站分享给您身边的朋友哦!!

版权声明:倡导尊重与保护知识产权。未经许可,任何人不得复制、转载、或以其他方式使用本站《原创》内容,违者将追究其法律责任。本站文章内容,部分图片来源于网络,如有侵权,请联系我们修改或者删除处理。

编辑推荐

热门文章