首页 后端开发 Golang 当Golang遇到高并发秒杀~

当Golang遇到高并发秒杀~

Oct 29, 2020 pm 03:10 PM
golang

下面由golang教程栏目给大家介绍当Golang遇到高并发秒杀,希望对需要的朋友有所帮助!

当Golang遇到高并发秒杀~

遇到GO语言也是偶尔的一次机会,工作上做架构相关的事情,对新发展比较火爆的语言肯定要关注下。就这样步入了GO语言的世界,GO给我带来了全新的体验;

  一直做一件事情的人往往会被一件事情所困,开始实践GO语言的时候总感觉哪哪都别扭,特别是把结构体当成类,还有结构体的继承,写面向对想多了开始还真扭不过来。不过写的多了渐渐地也习惯了,甚至感觉越来越顺眼。

  在熟悉了GO一段时间后,也停止了一会,脑子里一直在想着GO的简洁(代码风格一致,用起来简练不拖泥带水,部署极其简单,编译速度用快来形容),能给项目系统和架构带来哪些改变。但是当时一时半会儿还真没想到有多大帮助,后来系统逐步开始用GO实现,用的多了慢慢地发现:

  咦~,部署再也不要搭建依赖环境了(不部署环境发布,刚开始还真有点不习惯,总感觉少来点什么;

  别人写的代码看着也没有抵触心理,虽然说有的代码不是自己写的,仔细阅读的时候就感觉像是自己写的,写JAVA 和PHP的时候 阅读代码哪是从内心拒绝的;

  开发某个微服务接口一切变得简单了,写个main,写个接口,提交,秒秒种就上线了~;

  上面主要说了自己和GO的相遇还有GO给我带来的初步影响,就在某天晚上我脑袋里突然蹦出一个想法,GO语言用简洁带来诸多提升,从事的架构系统是否也能利用GO来简化,降低系统复杂度?这个想法从蹦出来,就一直在我脑袋里徘徊。回想刚开始从事架构相关事情的时候,一看到讲中间件有什么原理,有什么优化能提高性能就非常兴奋,埋头苦研直到自己感觉掌握(当然现在也要),然后就信誓旦旦的用到系统中,感觉系统架构用中间件组件越多越好,越多越显得自己做的架构有多厉害。但是随着越做越久你就会发现,系统能用就行,不能为了架构而架构。从传统技术栈上做减法同样需要深厚的功底,因为只有充分知道技术原理才能替换,也才敢想敢干,不出问题。常言道:“条条大陆通罗马”,从个人较角度讲架构要适合当时的业务,达到用尽可能少的代价完成尽可能多的事情就算达到架构设计的目标了,就比如消耗服务器资源相同情况下能支撑好几倍甚至好几十倍的请求,达到相同请求量的情况下,实现和部署非常简单可操作等。GO的思想这段时间就一直这么潜移默化地影响这我。

  直到我们公司决定做微服务,刚开始我们用java做微服务。后来想了下其它语言是否也能做微服务,自然而然的就想到了GO,经过一番折腾后感觉还可以,就用GO开始写点微服务,写着写着就发现Golang 写微服务还挺顺手,效率那个高啊,也不用封装tomcat(这东西放jar包里,感觉特别不合适),二进制不用系统依赖都能在docker里面跑(不信你试试),就这样打心底来说越来越喜欢GO,后续的系统啥的也想用GO重构(写多了java多了遇到这么方便的真是感觉发现了春天)GO已经深入的影响了对系统的架构的看法。

  但究竟什么是架构,架构师又是这么炼成的 ?在这里分享下架构师炼成的八段艰辛:

  第一段:搬砖分为能办好砖和只会搬砖(有一批人留在了搬砖上,剩下的继续发展);

  第二段:能搬砖的可以分为要了解原理的和编程就是搬砖的;

  第三段:了解原理的又分为不断研究的和一知半解的;

  第四段:不断研究也能分成两种研究深入有广度和蜻蜓点水没广度的;

  第五段:有深度有广度的又分为纯技术型和业务型(开始分化);

  第六段:业务型要求有良好沟通,对系统和需求有一定设计把控能力的;

  第七段:这层很容易出现单纯使用堆中间件搭出“架构”系统的(初级架构师);

  第八段:这层很重要的一点,考虑问题足够细致、全面、善于沟通。做底层实现,理解底层原理,从业务,研发,测试,部署,维护升级多角度出发,因地制宜搭出的“架构”是为了开发效率,为了运行效率,为了开发质量,为了业务灵活和运行稳定,为了维护方便等等这样的人,可称为架构师(有这方面经验的回想下,有多少架构是表面上看着漂亮,实际用着难受的)。

  在做秒杀系统的时候,刚开始想到也最容易想到的传统技术栈就是,分布式session,Redis集群,分布式缓存,nginx反向代理nginx深层优化,机器优化,消息队列。没错Cap老师当年也是想到这些,也认为这些“成熟”的技术能应用到我们秒杀系统中没问题,况且公司内部讨论都感觉这些没问题。而且做了深入的研究比如:

  1.分布式Session 我们化了很大的力气,用Nginx+web+redis集群的方式来保存Session达到Session验证的目的,单点Session这块的架构就如下图所示:

https://img3.mukewang.com/5cff1c690001ee2815000528.jpg

  乍一看没问题,都是这么做的,真的大流量来了,就加Nginx,web服务器,也满足横向扩展,但是流量达到上亿级别以后我门的成本有点大,来回的网络请求session的时间我们也想压榨(那时候总感觉哪里不对),nginx在高流量下也时不时出现504。

  2.分布式缓存,这东西看着很简单,但是在大流量高并发系统里面是个非常复杂的事情,主要能遇到以下一些问题;

  1)缓存一致性(如果用这个的话,处理不好会出现超卖);

  2)缓存穿透;

  3)缓存雪崩;

  4)缓存黑洞问题:

  5)狗桩效应;

  .....还有许多需要注意的事情,总之分布式缓存用途很广泛也很有价值,但是要建立一个能够满足高并发,大流量的分布式缓存系统需要极强的技术团队支持,实现起来也特别的复杂这里就不在赘述;

  然而,我们看似没有问题的解决方案存在巨大的问题,实现“太不容易了”,门槛那个是高啊。用起来资源成本也是蛮高的,Session要满足横向扩展,web缓存也要满足横向扩展,包括redis集群也要满足,只能是不断的加集群;

  举个简单的例子(抛去其它因素,为了说明架构的重要性),假设我们现在单台机器,接口有5000QPS的处理能力(8核8G),要处理秒杀的上亿流量,秒杀开始瞬时流量按照300W预估,平均等待按照时间7秒计算(接口容忍到3.5WQPS),得出的结果也就是我们系统,就接口这块需要将近90台,这还没有算其它同等要求的的配套服务器,这些配套服务器简单说明如下;

  1.首先nginx层面要有同等级处理能力(每台不优化大概2WQPS,预估20台左右);

  2.web接口同样要扩展到相应等级(预估的90台);

  3.Reids集群多商品有情况下有左右(单独商品,大量访问量的情况下集群也没用);

  上面是分布式Session要满足的机器需求,还没算上分布式缓存,同学们大概可以感觉到做个和做好秒杀系统有多么不容易了,部署的复杂度也还没考虑。实施起来真是复杂,经验4-5年一两个人短时间还真完成不了。能想出其它的办法来简化吗?答案是:有的。首先要理解原理,其次要从架构上做减法。不用就没有必要优化。

  要从哪些地方优化呢?

  1)Session在秒杀并发里,根据权限验证的原理是可以省略的;

  2)我们可以不用分布式缓存(用接口代替);

  3)把nginx也省了(降低运维难度);

  4)redis集群也可以省略;

  这么一除二去,秒杀怎么做啊?用java和php不是不能实现,而是实现起来可以比较吃力,但是现在可以结合GO语言特性来给我们提供新的思路;

  1.Nginx 可以省略,直接用GO启动端口暴露服务(这里可以省去nginx);

  2.采用cookie方式或者wt方式来代替分布式Session方案,服务器端代码层面验证;

  3.超卖采用接口形式代替redis集群;

  4.负载均衡采用廉价的SLB(避免了Nginx);

  秒杀优化以后总统架构可以展示为下图结构,详细做法请参阅《Go高并发秒杀实践》:

https://img4.mukewang.com/5cffbcdf0001568614020843.jpg

  从改造后的结果来看我们主要列下:

  1.web应用都采用Go部署进制文件的方法,centos服务器不需要按照任何依赖(极大的方便了部署):

  2.采用SLB廉价实用方案避免了nginx的反向代理,甚至高级lua脚本也避免了;

  3.redis集群在这里也被避免了,采用接口的方式提供服务;

  整个技术栈只需要会:GO,RabbitMQ,Mysql就能完成高并发秒杀系统,首先从易操作上就很诱人;下面大家可以在调整后的架构上推演下(目前单机GO提供web接口,在未经过优化的情况下大概能达到2WQPS):

  1.单机GO接口权限验证性能提高4倍,部署复杂度可以说已经接近与零(无nginx,无redis集群,运行也无依赖环境);

  2.随着流量等级的不断提高只需要添加web服务器和数量控制服务器,没有其它服务开销(扩展性上可以说是尽最大的可能降低了成本,成正比例增长模式,且无性能瓶颈);

  3.对比传统方案,服务器数量降低不止4倍(大家可以在原有的基础上计算下);

  上面的解决方案是在GO语言的简单的基础上实现的,恰巧GO部署方便提高了易实现性,有恰好GO能提供web服务减少了外部依赖(本身web务性能也很高)。有了GO的两个恰到好处的特性,在配合架构上减法操作,让秒杀系统整体实现不在是件难事,当然java和PHP都可以做上图中调整后的秒杀架构,但是从多方面考虑来讲,总统还是GO优势明显点。

  回首看方案感觉是Go带动了思维模式的改变,本身简单带动了实现简单,本身高效稳定带动了架构优化。好的系统架构就应该简单,高效,易实现;

以上是当Golang遇到高并发秒杀~的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
4 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

如何使用 Golang 安全地读取和写入文件? 如何使用 Golang 安全地读取和写入文件? Jun 06, 2024 pm 05:14 PM

在Go中安全地读取和写入文件至关重要。指南包括:检查文件权限使用defer关闭文件验证文件路径使用上下文超时遵循这些准则可确保数据的安全性和应用程序的健壮性。

如何为 Golang 数据库连接配置连接池? 如何为 Golang 数据库连接配置连接池? Jun 06, 2024 am 11:21 AM

如何为Go数据库连接配置连接池?使用database/sql包中的DB类型创建数据库连接;设置MaxOpenConns以控制最大并发连接数;设置MaxIdleConns以设定最大空闲连接数;设置ConnMaxLifetime以控制连接的最大生命周期。

golang框架的优缺点比较 golang框架的优缺点比较 Jun 05, 2024 pm 09:32 PM

Go框架凭借高性能和并发性优势脱颖而出,但也存在一些缺点,如相对较新、开发者生态系统较小、缺少某些功能。此外,快速变化和学习曲线可能因框架而异。Gin框架以其高效路由、内置JSON支持和强大的错误处理而成为构建RESTfulAPI的热门选择。

Golang框架与Go框架:内部架构与外部特性对比 Golang框架与Go框架:内部架构与外部特性对比 Jun 06, 2024 pm 12:37 PM

GoLang框架与Go框架的区别体现在内部架构和外部特性上。GoLang框架基于Go标准库,扩展其功能,而Go框架由独立库组成,实现特定目的。GoLang框架更灵活,Go框架更容易上手。GoLang框架在性能上稍有优势,Go框架的可扩展性更高。案例:gin-gonic(Go框架)用于构建RESTAPI,而Echo(GoLang框架)用于构建Web应用程序。

Golang 框架中的错误处理最佳实践有哪些? Golang 框架中的错误处理最佳实践有哪些? Jun 05, 2024 pm 10:39 PM

最佳实践:使用明确定义的错误类型(errors包)创建自定义错误提供更多详细信息适当记录错误正确传播错误,避免隐藏或抑制根据需要包装错误以添加上下文

如何在 Golang 中将 JSON 数据保存到数据库中? 如何在 Golang 中将 JSON 数据保存到数据库中? Jun 06, 2024 am 11:24 AM

可以通过使用gjson库或json.Unmarshal函数将JSON数据保存到MySQL数据库中。gjson库提供了方便的方法来解析JSON字段,而json.Unmarshal函数需要一个目标类型指针来解组JSON数据。这两种方法都需要准备SQL语句和执行插入操作来将数据持久化到数据库中。

如何解决golang框架中常见的安全问题? 如何解决golang框架中常见的安全问题? Jun 05, 2024 pm 10:38 PM

如何在Go框架中解决常见的安全问题随着Go框架在Web开发中的广泛采用,确保其安全至关重要。以下是解决常见安全问题的实用指南,附带示例代码:1.SQL注入使用预编译语句或参数化查询来防止SQL注入攻击。例如:constquery="SELECT*FROMusersWHEREusername=?"stmt,err:=db.Prepare(query)iferr!=nil{//Handleerror}err=stmt.QueryR

如何找出 Golang 正则表达式匹配的第一个子字符串? 如何找出 Golang 正则表达式匹配的第一个子字符串? Jun 06, 2024 am 10:51 AM

FindStringSubmatch函数可找出正则表达式匹配的第一个子字符串:该函数返回包含匹配子字符串的切片,第一个元素为整个匹配字符串,后续元素为各个子字符串。代码示例:regexp.FindStringSubmatch(text,pattern)返回匹配子字符串的切片。实战案例:可用于匹配电子邮件地址中的域名,例如:email:="user@example.com",pattern:=@([^\s]+)$获取域名match[1]。

See all articles