您的位置:首页 > 其它

秒杀核心设计——防止超卖、高并发与varnish详解

2015-11-16 22:58 302 查看
1、商品详情页面静态化

2、varnish加速

Varnish可以有效降低web服务器的负载,提升访问速度。根据官方的说法,Varnish是一个cache型的HTTP反向代理。

按照HTTP协议的处理过程,web服务器接受请求并且返回处理结果,理想情况下服务器要在不做额外处理的情况下,立即返回结果,但实际情况并非如此。本文将分析在web服务器处理请求的过程中,Varnish能起到什么作用

web服务器的实现千差万别,但典型的处理过程是相同的,都要经过一系列的步骤来处理接收到的每个请求。有可能需要启动一个进程来处理请求,有可能需要从磁盘上载入文件,或者启动内部线程来编译执行一些脚本。在执行脚本的过程中,还会有进行很多别的动作,比如进行数据库查询,读取文件等等。当成百上千个请求并发访问时,服务器的负载会很快上升,出现系统资源不够的情况。一种更糟的情况是,很多请求是重复的,但web服务器无法记住曾经作出的响应,还会重复上面复杂的处理过程。

当把Varnish部署上之后,web请求的处理过程会有一些变化。客户端的请求将首先被Varnish接受。Varnish将分析接收的请求,并将其转发到后端的web服务器上。后端的web服务器对请求进行常规的处理,并将依次将处理结果返回给Varnish。

但Varnish的功能并非仅限于此。Varnish的核心功能是能能将后端web服务器返回的结果缓存起来,如果发现后续有相同的请求,Varnish将不会将这个请求转发到web服务器,而是返回缓存中的结果。这将有效的降低web服务器的负载,提升响应速度,并且每秒可以响应更多的请求。Varnish速度很快的另一个主要原因是其缓存全部都是放在内存里的,这比放在磁盘上要快的多。诸如此类的优化措施使得Varnish的相应速度超乎想象。但考虑到实际的系统中内存一般是有限的,所以需要手工配置一下缓存的空间限额,同时避免缓存重复的内容。

下面来看一下Varnish的安装过程。可以从源码进行安装,也可以直接使用一些发行版中的预编译包。当期Varnish的版本是3.0.3(译者注:目前最新是2013年6月17日发布的3.0.4版),本文将基于3.0.3进行源码安装。需要注意的是,2.X版的Varnish和3.X的配置文件格式发生了变化。可以从Varnish的官方网站上找到2.x到3.x升级的细节。

从源码进行安装经常遇到的问题是系统缺少某些依赖的文件。可以从Varnish的安装文档里找到编译所需的所有依赖的文件。

以root身份运行如下命令来下载和安装Varnish。

cd /var/tmp
wget http://repo.varnish-cache.org/source/varnish-3.0.3.tar.gz tar xzf varnish-3.0.3.tar.gz
cd varnish-3.0.3
sh autogen.sh
sh configure
make
make test
make install


Vanish将安装在/usr/local目录下。主程序的完整路径为:/usr/local/sbin/varnishd,默认的配置文件为:/usr/local/etc/varnish/default.vcl

在运行varnishd之前,需要先配置后端的web服务器,参照如下格式编辑default.vcl文件,更改为你自己web服务器配置。

backend default {
.host = "127.0.0.1";
.port = "80";
}


用如下命令启动Varnishd:

/usr/local/sbin/varnishd -f /usr/local/etc/varnish/default.vcl
↪-a :6081 -P /var/run/varnish.pid -s malloc,256m


执行完毕后,Varnish将进入后台运行,同时返回命令行状态。需要注意的是,Varnish运行时会同时启动两个进程,一个主进程,一个是子进程,如果子进程出现问题,主进程将重新生成一个子进程。

Varnishd 的启动选项

-f : 指定配置文件位置

-a : varnish监听的本地地址和端口。

-P :PID文件位置,用来关闭Varnish

-s :cache配置。默认使用256M内存

如果从一些包管理器来安装varnish,可能安装完毕后就会自动运行。这种情况下需要先停掉它。并使用上述命令选项来运行。否则一些配置可能和本文例子中的不同了。可以用下面的命令来检查varnish的运行情况和配置。

/usr/bin/pgrep -lf varnish


启动完毕之后,Varnish就可以处理并转发请求了。在转发过程中,varnish会尽可能的缓存结果。我们通过下面几个简单的GET请求,来看看varnish是如何工作的。首先,运行如下命令:

/usr/local/bin/varnishlog
/usr/local/bin/varnishstat


下面的GET命令是perl的libwww-perl中的。使用这个命令可以看到varnish返回的HTTP响应的细节。如果你的系统里没有安装libwww-perl,也可以使用Firefox中live HTTP Headers扩展,或者使用其他类似工具也可以。

GET -Used http://localhost:6081/[/code] 


**这里GET命令的选项无所谓。需要注意的是varnish返回的响应,varnish会增加三个相应头信息,分别是“X-Varnish”、“Via”和“Age”。这些头信息在Varnish的处理过程中非常有用。X-Varnish头信息的后面会有一个或两个数字,如果是一个数字,就表明varnish在缓存中没有发现这个请求,这个数字的含义是varnish为这个请求所做的标记ID。如果X-Varnish后是两个数字,就表明varnish在缓存中命中了这个请求,第一个数字是请求的标识ID,第二个数字是缓存的标识ID。“Via”头信息表明这个请求将经过一个代理。“Age”头信息标识出这个请求将被缓存多长时间(单位:秒)。首次请求的“Age”为0,后续的重复请求将会使Age值增大。如果后续的请求没有是“Age”增加,那就说明varnish没有缓存这个响应的结果。

显示varnish和客户端之间的通信(忽略后端web服务器):

/usr/local/bin/varnishlog -b


显示varnish接收到的HTTP头信息(既有客户端请求的,也有web服务器响应的):

/usr/local/bin/varnishlog -c -i RxHeader


只显示web服务器响应的头信息:

/usr/local/bin/varnishlog -Dw /var/log/varnish.log


从/var/log/varnish.log中读取所有日志信息

kill `cat /var/run/varnish.pid`


这个命令会从/var/run/varnish.pid中读取varnish的主进程的PID,并给这个进程发送TERM信号,从而关闭varnish。

现在通过上述命令,我们可以控制varnish的启动和关闭,可以检查缓存的命中情况,下一个问题是varnish到底缓存了什么,会存多久?

varnish的默认缓存策略是偏向保守的(可以通过配置改变)。它默认只缓存get请求和HEAD请求。不会缓存带有Cookie和认证信息的请求,也不会缓存带有Set-Cookie或者有变化的头信息的响应。varnish也会检查请求和响应中的Cache-Control头信息,这个头信息中会包含一些选项来控制缓存行为。当Cache-control中Max-age的控制和默认策略冲突时,varnish不会单纯的根据Cache-control信息就改变自己的缓存行为。例如:Cache-Control: max-age=n,n为数字,如果varnish收到web服务器的响应中包含max-age,varnish会以此值设定缓存的过期时间(单位:秒),否则varnish将会设置为参数配置的时间,默认为120秒。

注意:

varnish的默认配置可以适应多数情况。例如,默认的default_ttl缓存过期时间是120秒。配置文件的详细解释可以阅读varnishd的man page。如果你想改变某些默认设置,一种方式是通过命令行varnishd加上-p参数,这将重启varnishd,并清空缓存。另外一种方式是使用varnish的管理接口,要使用varnish的管理接口需要以-T参数启动varnish,这个参数指定了,varnish管理接口的监听端口。然后使用varnishadm命令连接到varnish的管理接口上,然后实时的查询varnish的运行参数,或者更改新的参数,这些都不需要重启varnish。

想要了解详细的情况,可以参阅varnishd、varnishadm和varnish-cli的man page。

一般情况下我们会改变varnish的缓存行为,定制自己的缓存策略。可以将配置写入默认的default.vcl文件,VCL是varnish的配置文件的格式,像一种简单的脚本语言。可以通过vcl的man page来了解详细的格式,推荐阅读。

在修改default.vcl配置之前,我们先来看一下varnish处理http请求的一个完整过程。我们将之成为一个请求/响应周期(request/response cycle)。这个过程始于varnish收到客户端的请求,varnish将检查这个请求,并将其标记存储,接下来varnish将根据一定的策略决定是将这个请求直接转发,还是检查缓存。如果是第一种情况,varnish会将请求直接转发到后端的服务器上,并且将服务器的响应返回给你客户端。如果是第二种情况,varnish会进行一个缓存查询的过程,如果缓存命中,varnish会将缓存中结果返回给客户端,如果缓存中没有,varnish会将此请求转发给后端的服务器,并将服务器的响应先进行缓存,然后再转发给客户端。

了解完varnish对请求和响应处理的过程之后,我们来讨论一下如何改变varnish的缓存策略。varnish有一系列的子功能来完成上述处理过程,每一个子功能完成处理过程的一个部分。每一个子功能的执行结果传递给下一个子功能。所以我们可以通过改变子功能的返回值来改变varnish的处理动作。每一个子功能都在default.vcl中有一个默认定义,可以通过改变这些值来定制varnish的功能。

3、数据库方面

第一个表:buy_record(用户秒杀记录表)

第二个表:buy_goods(商品表)

对(uid,goods_id)添加唯一索引

start transaction

insert into buy_record

if(唯一索引报错)

抛出异常,说明已经秒杀过该商品

update buy_goods set goods_num=goods_num-1 where goods_id = $good_id and goods_num>0;**
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: