有多种释义,包括计量单位,著名纸模型品牌等等。在生物医学领域,GPM是The Global Proteome Machine的缩写,其支持的生物信息学开源软件项目X!Tandem在蛋白质组学方面有很强的应用性。
另外,“GPM”也可解释为“良好的生产规范”,是药品、食品等行业强制执行的标准,是在生产过程中对产品质量及卫生安全实施自主管理的制度。
扩展资料
G、P、M 是 Go 调度器的三个核心组件,各司其职。在它们精密地配合下,Go 调度器得以高效运转,这也是 Go 天然支持高并发的内在动力。今天这篇文章我们来深入理解 GPM 模型。
先看 G,取 goroutine 的首字母,主要保存 goroutine 的一些状态信息以及 CPU 的一些寄存器的值,例如 IP 寄存器,以便在轮到本 goroutine 执行时,CPU 知道要从哪一条指令处开始执行。
当 goroutine 被调离 CPU 时,调度器负责把 CPU 寄存器的值保存在 g 对象的成员变量之中。
当 goroutine 被调度起来运行时,调度器又负责把 g 对象的成员变量所保存的寄存器值恢复到 CPU 的寄存器。
参考资料来源:百度百科-gpm
一、关于连接池
一个数据库服务器只拥有有限的资源,并且如果你没有充分使用这些资源,你可以通过使用更多的连接来提高吞吐量。一旦所有的资源都在使用,那么你就不 能通过增加更多的连接来提高吞吐量。事实上,吞吐量在连接负载较大时就开始下降了。通常可以通过限制与可用的资源相匹配的数据库连接的数量来提高延迟和吞 吐量。
如何在Go语言中使用Redis连接池
如果不使用连接池,那么,每次传输数据,我们都需要进行创建连接,收发数据,关闭连接。在并发量不高的场景,基本上不会有什么问题,一旦并发量上去了,那么,一般就会遇到下面几个常见问题:
性能普遍上不去
CPU 大量资源被系统消耗
网络一旦抖动,会有大量 TIME_WAIT 产生,不得不定期重启服务或定期重启机器
服务器工作不稳定,QPS 忽高忽低
要想解决这些问题,我们就要用到连接池了。连接池的思路很简单,在初始化时,创建一定数量的连接,先把所有长连接存起来,然后,谁需要使用,从这里取走,干完活立马放回来。 如果请求数超出连接池容量,那么就排队等待、退化成短连接或者直接丢弃掉。
二、使用连接池遇到的坑
最近在一个项目中,需要实现一个简单的 Web Server 提供 Redis 的 >
有个服务会大量使用延迟消息,进行事件处理。随着业务量不断上涨。在晚间、节假日等流量高峰期消息延迟消息队列限流会导致事件丢失,影响业务。与下游沟通后给上调到了最大限流值,问题依然存在,于是决定自己搞一套降级方案。
下游服务触发限流时,能降级部分流量到本地延迟队列,把业务损失降到最低。
本地延迟队列承接部分mq流量
流程如下:
1 使用zset 存储延迟消息,其中:score为执行时间,value为消息体
2 启动协程轮询zset,获取score最小的10条数据,协程执行间隔时间xs
如果最小分值小于等于当前时间戳,则发送消息
若最小分值大于当前时间戳,sleep等待执行
需要对key进行hash,打散到多个分片中,避免大key和热key问题,官方大key定义
因此,需保证每个key中value数量n<5000,单个value大小不超过 10240/n kb
假设承接10w qps,如何处理?
10w qps延迟120s时,最开始消息队列会积累100000120=12000000条消息
假如每条消息大小500b,需占用存储6000000kb = 6000Mb = 6GB
为避免大key问题,每个zset存放4000个元素,需要哈希到3000(3000是key的数量,可配置)个zset中。
整个集群假设500台实例,每个处理qps平均在200左右。
单实例消费能力计算:
遍历每个zset,针对每个zset起goroutine处理,此示例中需要 起3000个
但是每秒能处理成功的只有200个,其他都在空跑
综上:
将redis key分片数n和每次处理的消息数m进行动态配置,便于调整
当流量上涨时,调大分片数n和单实例单分片并发数m即可,假如消费间隔200ms,集群处理能力为nm5 qps
n = (qps 120) / 4000
若qps=q,则计算公式如下
zadd = q
zRange = 500 5 n / 500
zRemove = q
setNx = 500 5 n
若10w qps,则
读qps = 15000 + 50030005 =7515000,写 20w
pros
redis 读写性能好,可支持较大并发量,zrange可直接取出到达执行时间的消息
cons
redis 大key问题导致对数据量有一定的限制
分片数量扩缩容会漏消费,会导致事件丢失,业务有损
key分片数量过多时,redis读写压力较大
机器资源浪费,3000个协程,单实例同一秒只有200个针对处理,其他都在空跑
流程如下:
使用带缓冲的channel来实现延迟队列,channel中存放的数据为消息体(包括执行时间),channel能保证先进先出
从channel中取出数据后,判断是否到达执行时间
到达,同步发送mq
未到达,sleep 剩余执行时间,然后再次执行
从channel读出的数据如果未到达执行时间,无法再次放入channel中,需要协程sleep(执行时间-当前时间)
10w qps延迟120s时,最开始消息队列会积累100000120=12000000条消息,假设每条消息大小500b,需要6G存储空间
channel 大小 = (qps120)/ c , c=集群实例数,c=500 => channel大小为24000,占用12M内存
要处理10w qps,分摊到每个机器的处理速度为 100000/500 = 200,假设单协程处理10qps,开20个即可。
pros:
本地存储,相比redis,读写速度更快;协程数量少,开销低;资源利用率较方案一高
cons:
稳定性不如redis,实例故障可能导致数据丢失;worker池和channel扩缩容依赖服务重启,成本高速度慢
综上,我们以10w qps为例,对比两种方案在以下指标差异,选择方案二。
附上demo
以上就是关于GPM是什么意思呢全部的内容,包括:GPM是什么意思呢、如何在 Go 语言中使用 Redis 连接池、golang实现本地延迟队列等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)