首页 » 网站推广 » 小米php抢购功效技巧_小米手机越来越随意马虎抢的背后抢购系统的优化

小米php抢购功效技巧_小米手机越来越随意马虎抢的背后抢购系统的优化

访客 2024-12-15 0

扫一扫用手机浏览

文章目录 [+]

这次米粉节活动,是小米电商的成人礼,是一次主要的考试。
小米网从网站前端、后台系统、仓储物流、售后等各个环节,都将接管一次全面的压力测试。

10点整,一波流量高峰即将到来,几百万用户将准点挤入小米网的做事器。
而首先欢迎压力冲击的,便是挡在最前面的抢购系统。

小米php抢购功效技巧_小米手机越来越随意马虎抢的背后抢购系统的优化

而这个抢购系统是重新开拓、刚刚上线不久的,这是它第一次接管这样严厉的磨练。

小米php抢购功效技巧_小米手机越来越随意马虎抢的背后抢购系统的优化
(图片来自网络侵删)

系统能不能顶住压力?能不能顺畅精确地实行业务逻辑?这些问题不到抢购高峰那一刻,谁都不能百分百确定。

9点50分,流量已经爬升得很高了;10点整,抢购系统自动开启,购物车中已经顺利加入了抢购商品。

一两分钟后,热门的抢购商品已经售罄自动停滞抢购。
抢购系统抗住了压力。

我长舒一口气,之前积累的压力都消散了。
我坐到角落的沙发里,默默回忆抢购系统所经历的那些触目惊心的故事。
这可真是一场很少人有机会经历的探险呢。

抢购系统是若何出身的

韶光回到2011年底。
小米公司在这一年8月16日首次发布了手机,急速引起了市场轰动。
随后,在一天多的韶光内预约了30万台。
之后的几个月,这30万台小米手机通过排号的办法依次发货,到当年年底全部发完。

然后便是开放购买。
最初的开放购买直接在小米的商城系统上进行,但我们那时候完备低估了“抢购”的威力。
瞬间爆发的平常几十倍流量迅速淹没了小米网商城做事器,数据库去世锁、网页刷新超时,用户购买体验非常差。

市场需求不等人,一周后又要进行下一轮开放抢购。
一场风暴就等在前方,而我们只有一周的韶光了,全体开拓部都承担着巨大的压力。

小米网可以采取的常规优化手段并不太多,增加带宽、做事器、探求代码中的瓶颈点优化代码。
但是,小米公司只是一家刚刚成立一年多的小公司,没有那么多的做事器和带宽。
而且,如果代码中有瓶颈点,纵然能增加一两倍的做事器和带宽,也一样会被瞬间爆发的几十倍负载所冲毁。
而要优化商城的代码,韶光上已没有可能。
电商网站很繁芜,说不定某个不起眼的次要功能,在高负载情形下就会成为瓶颈点拖垮全体网站。

这时开拓组面临一个选择,是连续在现有商城上优化,还是单独搞一套抢购系统?我们决定冒险一试,我和几个同事一起突击开拓一套独立的抢购系统,希望能够绝境逢生。

摆在我们面前的是一道彷佛无解的难题,它要达到的目标如下:

只有一周韶光,一周内完成设计、开拓、测试、上线;失落败的代价无法承受,系统必须顺畅运行;抢购结果必须可靠;面对海量用户的并发抢购,商品不能卖超;一个用户只能抢一台手机;用户体验只管即便好些。

设计方案便是多个限定条件下求得的解。
韶光、可靠性、本钱,这是我们面临的限定条件。
要在那么短的韶光内办理难题,必须选择最大略可靠的技能,必须是经由足够验证的技能,办理方案必须是最大略的。

在高并发情形下,影响系统性能的一个关键成分是:数据的同等性哀求。
在前面所列的目标中,有两项是关于数据同等性的:商品剩余数量、用户是否已经抢购成功。
如果要担保严格的数据同等性,那么在集群中须要一个中央做事器来存储和操作这个值。
这会造成性能的单点瓶颈。

在分布式系统设计中,有一个CAP事理。
“同等性、可用性、分区容忍性”三个要素最多只能同时实现两点,不可能三者兼顾。
我们要面对极度的爆发流量负载,分区容忍性和可用性会非常主要,因此决定捐躯数据的强同等性哀求。

做出这个主要的决定后,剩下的设计决定就自然而然地产生了:

技能上要选择最可靠的,由于团队用PHP的居多,以是系统利用PHP开拓;抢资格过程要最简化,用户只需点一个抢购按钮,返回结果表示抢购成功或者已经售罄;对抢购要求的处理只管即便简化,将I/O操作掌握到最少,减少每个要求的韶光;只管即便去除性能单点,将压力分散,整体性能可以线性扩展;放弃数据强同等性哀求,通过异步的办法处理数据。

末了的系统事理见后面的初版抢购系统事理图(图1)。

图1 初版抢购系统事理图

系统基本事理:在PHP做事器上,通过一个文件来表示商品是否售罄。
如果文件存在即表示已经售罄。
PHP程序吸收用户抢购要求后,查看用户是否预约以及是否抢购过,然后检讨售罄标志文件是否存在。
对预约用户,如果未售罄并且用户未抢购成功过,即返回抢购成功的结果,并记录一条日志。
日志通过异步的办法传输到中央掌握节点,完成记数等操作。

末了,抢购成功用户的列表异步导入阛阓系统,抢购成功的用户在接下来的几个小时内下单即可。
这样,流量高峰完备被抢购系统挡住,商城系统不须要面对高流量。

在这个分布式系统的设计中,对持久化数据的处理是影响性能的主要成分。
我们没有选择传统关系型数据库,而是选用了Redis做事器。
选用Redis基于下面几个情由。

首先须要保存的数据是范例的Key/Value对形式,每个UID对应一个字符串数据。
传统数据库的繁芜功能用不上,用KV库正得当。
Redis的数据是in-memory的,可以极大提高查询效率。
Redis具有足够用的主从复制机制,以及灵巧设定的持久化操作配置。
这两点恰好是我们须要的。

在全体系统中,最频繁的I/O操作,便是PHP对Redis的读写操作。
如果处理不好,Redis做事器将成为系统的性能瓶颈。

系统中对Redis的操作包含三种类型的操作:查询是否有预约、是否抢购成功、写入抢购成功状态。
为了提升整体的处理能力,可采取读写分离办法。

所有的读操作通过从库完成,所有的写操作只通过掌握端一个进程写入主库。

在PHP对Redis做事器的读操作中,须要把稳的是连接数的影响。
如果PHP是通过短连接访问Redis做事器的,则在高峰时有可能堵塞Redis做事器,造成雪崩效应。
这一问题可以通过增加Redis从库的数量来办理。

而对付Redis的写操作,在我们的系统中并没有压力。
由于系统是通过异步办法,网络PHP产生的日志,由一个管理真个进程来顺序写入Redis主库。

另一个须要把稳的点是Redis的持久化配置。
用户的预约信息全部存储在Redis的进程内存中,它向磁盘保存一次,就会造成一次等待。
严重的话会导致抢购高峰时系统前端无法相应。
因此要只管即便避免持久化操作。
我们的做法是,所有用于读取的从库完备关闭持久化,一个用于备份的从库打开持久化配置。
同时利用日志作为应急规复的保险方法。

全体系统利用了大约30台做事器,个中包括20台PHP做事器,以及10台Redis做事器。
在接下来的抢购中,它顺利地抗住了压力。
回忆起当时的场景,真是非常的触目惊心。

第二版抢购系统

经由了两年多的发展,小米网已经越来越成熟。
公司准备在2014年4月举办一次盛大的“米粉节”活动。
这次持续一整天的购物狂欢节是小米网电商的一次成人礼。
商城前端、库存、物流、售后等环节都将经历一次磨练。

对付抢购系统来说,最大的不同便是一天要经历多轮抢购冲击,而且有多种不同商品参与抢购。
我们之前的抢购系统,是按照一周一次抢购来设计及优化的,根本无法支撑米粉节繁芜的活动。
而且经由一年多的修修补补,初版抢购系统积累了很多的问题,恰好趁此机会对它进行彻底重构。

第二版系统紧张关注系统的灵巧性与可运营性(图2)。
对付高并发的负载能力,稳定性、准确性这些哀求,已经是根本性的最低哀求了。
我希望将这个别系做得可灵巧配置,支持各种商品各种条件组合,并且为将来的扩展打下良好的根本。

图2 第二版系统总体构造图

在这一版中,抢购系统与商城系统依然隔离,两个别系之间通过约定的数据构造交互,信息通报精简。
通过抢购系统确定一个用户抢得购买资格后,用户自动在商城系统中将商品加入购物车。

在之前初版抢购系统中,我们后来利用Go措辞开拓了部分模块,积累了一定的履历。
因此第二版系统的核心部分,我们决定利用Go措辞进行开拓。

我们可以让Go程序常驻内存运行,各种配置以及状态信息都可以保存在内存中,减少I/O操作开销。
对付商品数量信息,可以在进程内进行操作。
不同商品可以分别保存到不同的做事器的Go进程中,以此来分散压力,提升处理速率。

系统做事端紧张分为两层架构,即HTTP做事层和业务处理层。
HTTP做事层用于坚持用户的访问要求,业务处理层则用于进行详细的逻辑判断。
两层之间的数据交互通过行列步队来实现。

HTTP做事层紧张功能如下:

进行基本的URL精确性校验;对恶意访问的用户进行过滤,拦截黄牛;供应用户验证码;将正常访问用户数据放入相应商品行列步队中;等待业务处理层返回的处理结果。

业务处理层紧张功能如下:

吸收商品行列步队中的数据;对用户要求进行处理;将要求结果放入相应的返回行列步队中。

用户的抢购要求通过行列步队,依次进入业务处理层的Go进程里,然后顺序地处理要求,将抢购结果返回给前面的HTTP做事层。

商品剩余数量等信息,根据商品编号分别保存在业务层特定的做事器进程中。
我们选择担保商品数据的同等性,放弃了数据的分区容忍性。

这两个模块用于抢购过程中的要求处理,系统中还有相应的策略掌握模块,以及防刷和系统管理模块等(图3)。

图3 第二版系统详细构造图

在第二版抢购系统的开拓过程中,我们碰着了HTTP层Go程序内存花费过多的问题。

由于HTTP层紧张用于坚持住用户的访问要求,每个要求中的数据都会占用一定的内存空间,昔时夜量的用户进行访问时就会导致内存利用量不断上涨。
当内存占用量达到一定程度(50%)时,Go中的GC机制会越来越慢,但仍旧会有大量的用户进行访问,导致涌现“雪崩”效应,内存不断上涨,终极机器内存的利用率会达到90%以上乃至99%,导致做事不可用。

在Go措辞原生的HTTP包中会为每个要求分配8KB的内存,用于读缓存和写缓存。
而在我们的做事场景中只有GET要求,做事须要的信息都包含在HTTP Header中,并没有Body,实际上不须要如此大的内存进行存储。

为了避免读写缓存的频繁申请和销毁,HTTP包建立了一个缓存池,但其长度只有4,因此在大量连接创建时,会大量申请内存,创建新工具。
而昔时夜量连接开释时,又会导致很多工具内存无法回收到缓存池,增加了GC的压力。

HTTP协议是构建在TCP协议之上的,Go的原生HTTP模块中是没有供应直接的接口关闭底层TCP连接的,而HTTP 1.1中对连接状态默认利用keep-alive办法。
这样,在客户端多次要求做事端时,可以复用一个TCP连接,避免频繁建立和断开连接,导致做事端一贯等待读取下一个要求而不开释连接。
但同样在我们的做事场景中不存在TCP连接复用的需求。
当一个用户完成一个要求后,希望能够尽快关闭连接。
keep-alive办法导致已完成处理的用户连接不能尽快关闭,连接无法开释,导致连接数不断增加,对做事真个内存和带宽都有影响。

通过上面的剖析,我们的办理办法如下。

在无法优化Go措辞中GC机制时,要避免“雪崩效应”就要只管即便避免做事占用的内存超过限定(50%),在处于这个限定内时,GC可以有效进行。
可通过增加做事器的办法来分散内存压力,并尽力优化做事占用的内存大小。
同时Go 1.3也对其GC做了一定优化。
我们为抢购这个特定做事场景定制了新的HTTP包,将TCP连接读缓存大小改为1KB。
在定制的HTTP包中,将缓存池的大小改为100万,避免读写缓存的频繁申请和销毁。
当每个要求处理完成后,通过设置Response的Header中Connection为close来主动关闭连接。

通过这样的改进,我们的HTTP前端做事器最大稳定连接数可以超过一百万。

第二版抢购系统顺利完成了米粉节的磨练。

总结

技能方案须要依托详细的问题而存在。
分开了运用处景,无论多么酷炫的技能都失落去了代价。
抢购系统面临的现实问题繁芜多变,我们也依然在不断地摸索改进。

简历又被刷了,应届程序员简历就该这么写

理解常用缓存淘汰算法,这就够了

标签:

相关文章

大数据助力开店,精准定位,赢在起点

随着互联网技术的飞速发展,大数据已经渗透到了我们生活的方方面面。在商业领域,大数据的应用更是如火如荼。对于创业者来说,运用大数据开...

网站推广 2024-12-17 阅读0 评论0

大数据助力执勤,守护平安和谐

随着科技的发展,大数据技术在各个领域的应用日益广泛。在公安执勤工作中,大数据也发挥着越来越重要的作用。本文将探讨大数据如何助力执勤...

网站推广 2024-12-17 阅读0 评论0