演讲实录:使用 Go 开发秒杀系统的实践

嘉宾介绍

肖德时,数人云 CTO

负责数人云的研发及架构设计工作。关注领域包括 Docker,Mesos 集群, 云计算等领域。 肖德时之前为红帽 EngineeringService 部门内部工具组 Team Leader 。

以下为数人云“高并发”活动演讲实录

1.应对百万秒杀,不是写了一手好代码就能完成

我首先声明一点,百万并发的秒杀这个技术,不是说写了一手好代码就能完成的事情。最关键的地方就是要不断的优化,我今天讲的如何用 Go 语言来做秒杀,优化的东西我们不讲。

0.png 能不能在不优化的情况下,就用公有云的主机,用现有的程序,来构建一套扛住百万并发的系统,这是我今天想跟大家分享的。

1.png

  • 用 Go 来写秒杀。大家工作时间长了,心里面都有自己的架构,这张架构图是数人云的想法。要借助很多第三方资源,静态的部分肯定要有 CDN 来扛,安全方面解决不了,会用第三方服务来解决。百万并发不管怎么优化,用 CDN 再怎么挡,一百万的并发都得接住。如果接不住,秒杀就做不了,我们推荐用 Go来写。

  • 秒杀可以取巧。秒杀跟双十一,双十二有不一样的地方。双十一是有 1 亿请求就得接 1 亿请求,而且到支付阶段都要处理,这是最关键的技术。但是秒杀有一个取巧的地方,接了 100 万个请求,是可以只放进来 1000 个请求的,前面的请求都可以转到 CDN 去,这些请求接住后马上转走就可以了,这里就是取巧的地方。

如果用 Go 写一份秒杀系统,我们最关心的地方就是要写一个 Proxy,写一个 Queue Manager。

2.为什么用 Go 来写秒杀?

2.png

  • 我们为什么用 Go 来写秒杀,不用别的语言写秒杀?因为用 Go 写有一个好处,Go 语言是天生支持高并发,支持多线程并发管理的。而其他很多语言本身是不支持的,需要你自己去写,比如用 Java 写一个高并发程序,很多细节都需要自己处理。而用 Go 语言写,则不需要你来处理,Go 语言就帮你搞定了。高并发是有自己的原则,有自己的最佳实践。如果没有多年的经验,怎么去维护高并发下的多线程互斥操作,我个人觉得程序员如果能用工具就能写出高并发程序何乐而不为呢?用 Go 的好处就是我们只写逻辑的东西,高并发的东西用 Go 的 goroutine 来解决。

3.png

  • Go 首先是有一个 goroutine 的概念,就是把高并发的请求放在一个异步处理的通道里( Go Channel )。以前要维护这个高并发请求处理的情况,都需要自己写,但如果用 Go 语言,只需要一个语法,完全就能把所有的逻辑对接好,这就是一个很大的变化,这是我觉得 Go 语言最简单的地方,也是它威力所在。

4.png

3.云计算时代我们怎么玩高并发?

原来写高并发程序的时候,首先需要有配置很高的机器,万兆网卡,但是到了云计算时代我们怎么玩高并发,我给大家提供一个新的思路。

  • 第一,用标准机,2 Core CPU,4G 内存,CPU 还是虚拟的。另外告诉大家公有云目前最明显的一个特点,都是百兆、千兆网卡,你想买一个万兆虚拟网卡,没有。用 Apache ab 打满以后,普通的机器虽然它能接 1 万个并发,但是再加上后端的事务之后,一千个并发其实是它最好的一个容量,因为还要有扩容的地方。也就是说给它一个基准,就让它接 1000 个并发。

  • 第二,动态请求容量要规划好,主机一台不够可以搞上千台,照样能支持百万,这是我做的一个规划。用 Go 来写这个程序,不是从头开始写,我们可以找到现成的 Circuit Breaker 程序,设计完以后,Go 里面最大的一个情况就是做活动会有的突发情况,所以需要加一个熔断机制。就跟股市一样,直接给卡掉了。Go 语言是支持高并发的,但是它在接动态请求性能上面,暂时还打不过 Openresty/Nginx。但是这个没有关系,Go 语言一直也在发展,而且目前其性能也足够来做秒杀系统。接下来我们聊聊做秒杀的成本。

5.png

4.如何看待秒杀成本?

接下来给大家看一下我们的成本,细想一下,买一千台机器只要 500 块,带宽,为什么用公网带宽 20 兆,是有技巧的,一个小时也要 3000 块,负载均衡两个 318 元 一小时,这里面有隐含含义的。

  • 协调有限资源。首先第一点,给你 500 块开一千台虚机你开不了,必须找 IaaS 厂商的销售,你跟他说需要配合。这里面有很多业内行规,我只能说其实目前我们的网络环境,所有的资源是有限的。如果 IaaS 想挣钱,它必须找到更多的用户卖这个资源,而不是一家所有的资源全占了。

  • 让 IaaS 厂商对动态请求进行分流。资源要买这种 2 Core CPU , 4G 内存的,买一大堆的机器对 IaaS 厂商来说是一个非常大的损耗,因为太便宜了,但实际上他真正挣钱的是 64G 的,越高越好。这样他可以超卖,因为他的网卡也就是百兆,所以你根本用不了 64G 的全部资源,阿里最多也就是千兆,真正的网卡是万兆的。百万并发,一个 Nginx 肯定接不住,这个是要让 IaaS 厂商接, IaaS 有一个 ELB,ELB 可以对动态请求进行分流的。让他分流,分流之后再转到底层,底下就接一千个请求,就是分而治之的思路。

  • 高并发活动最贵的是带宽。总结一下,做一个百万并发的活动,最贵的是带宽。这还没有算 DDoS 的钱,CC 这种安全的钱,其实钱大部分都花在流量上了,这是目前的一个成本瓶颈。

6.png

  • 接住 Proxy 放进来的请求,然后放入发红包的队列

架构已经把百万订单接住了,接住了并没有解决第二步的问题,也就是发红包怎么办,要分到一个队列里面,这个队列是有技巧的,也就是说来了以后,先给他一个页面排队,还有一种是直接发。

这两种方式其实就是一种活动的策划,跟技术上应该没有多大的利弊关系,直接发红包效果可能比较好一点。所以最好能够全存在内存里,别存到本地硬盘。

因为到这里以后,就没有高并发了,要处理的是逻辑,可能客户会说,你给我中奖率提高一点,或者能给我动态调,大家记住,百万并发的时候一共就一秒,还没等你调呢,就完了,因为秒杀活动真的很快。

  • 这里没有高并发,稳定是第一位

稳定是最重要的,这一块 Go 语言是可以解决这个事情的。”随便”用一个 Go 的框架写一个 Web Server。记住程序运行起来后,并不代表运行的时候是稳定的。一共是两个,一个是秒杀时间,一个是 CountDown 秒杀开始的操作,程序写完了还有一个 Queue,Queue 就是用 Countdown 放开的数量,这是当前最成熟的一个解决方案,当然这个不能比之前京东、宜人贷这些大厂的做法,咱们就是说 MVP 创业嘛,最好用最成熟的方案。

  • Kafka 不是最好的方案

​ 因为有的时候会落地。我们其实不想让它落地,就是一直占内存是最好的。单机的 Redis 在一台 2 Core CPU / 4G RAM 的机器能跑多少,6 万并发没有问题,我就让它跑 6 万,因为便宜,一千台机器才 500 块每小时。当然这里是理论值。如果给你 500 块钱,让你去 IaaS商那里买 1000 台机器,你是买不到的。

7.png 不管用脚本还是用各种分布式的架构,到数人云这里,推荐的是分布式集群,之所以用这个来管,是因为做一次活动就是要快。数人云的控制程序不管在哪一个 IaaS 上都没有问题,直接将部署控制软件启动开,集群就被启动管理上了。刚才说的 Queue Manager 稳定性,基本上都靠 Docker 封装,封装以后快速发布到集群里面多份实例来容错稳定的。

  • 集群管理可以容错,死了还能自动负载重启服务,再加上一些监控事件。就可以知道什么时候是死的,什么时候是活的。
  • 遇到突发情况还能自动扩容,这种能力是原来不敢想的。但是现在因为有了云计算,我们终于有机会做这件事。原来还要买机器,现在有云主机随便可以尝试,这是我想做的事,这是我们数人云秒杀环境的参考。

秒杀就是要快,谢谢大家!